csharpfritz / InstantAPIs

A library that generates Minimal API endpoints for an Entity Framework context.
MIT License
448 stars 57 forks source link

MapInstantApis fails when key is not named id when using fluent interface [Bug] #71

Closed Wayne-Mather closed 1 year ago

Wayne-Mather commented 1 year ago

When using the fluent interface and not marking your keys with the [Key] annotation and those keys are not named "id" then the _IdLookup dictionary will not be filled with the keys for the entity.

This is due to MapApiExtensions having id hard coded into it. I wonder if it would be easy to add a configuration option to define how the property is matched? For example {ClassName}Id or {ClassName}_Id

I did a quick proof of concept by adding the following code in line 26 of MapApiExtensions:

var theType = typeof(C);
var keyName = $"{theType.Name}Id";
var idProp = theType.GetProperty("id", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) ??
           theType.GetProperty(keyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) ??
       theType.GetProperties().FirstOrDefault(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute)));
csharpfritz commented 1 year ago

Interesting idea.. let’s get a OR together and add it to the mix

Jeff

On Aug 20, 2022, at 17:08, Wayne Mather @.***> wrote:

 When using the fluent interface and not marking your keys with the [Key] annotation and those keys are not named "id" then the _IdLookup dictionary will not be filled with the keys for the entity.

This is due to MapApiExtensions having id hard coded into it. I wonder if it would be easy to add a configuration option to define how the property is matched? For example {ClassName}Id or{ClassName}_Id

I did a quick proof of concept by adding the following code in line 26 of MapApiExtensions:

var theType = typeof(C); var keyName = $"{theType.Name}Id"; var idProp = theType.GetProperty("id", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) ?? theType.GetProperty(keyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) ?? theType.GetProperties().FirstOrDefault(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute)));

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.

Wayne-Mather commented 1 year ago

Hi,

Can you confirm you have an off by 1 error in your message? O => P 😁

csharpfritz commented 1 year ago

Doh… yea. iPhone autocorrect isn’t a fan of PR.

Jeff

On Aug 21, 2022, at 18:04, Wayne Mather @.***> wrote:

 Hi,

Can you confirm you have an off by 1 error in your message? O => P 😁

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.

Wayne-Mather commented 1 year ago

I am doing something like the following:

app.MapInstantAPIs<MyContext>(config =>
{
    config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.All, "addressBook");
    config.PrimaryKeyMappingConvention(new List<string>() { "{ClassName}Id", "{ClassName}_Id", });
});

But it means changing Configuration from private to internal so that MapApiExtensions has access to it. Is this going to be a problem?

Wayne-Mather commented 1 year ago

Pull request created