I made a strongly typed id to prevent ids from entity A from being mixed with entity B, like so:
public record struct Id<TEntity>(int Value);
I also created and registered an IModelBinder
and a IModelBinderProvider
, so that I can have the following signature in my controller:
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetById(Id<Product> id);
This has one problem however. While int
parameters have the [FromRoute]
binding source by default, my Id
struct defaults to the [FromBody]
binding source, requiring me to explicitly add the attribute:
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetById([FromRoute] Id<Product> id);
So my question is, how can I change the default binding source from the binder/provider, without using annotations (including on Id
)?
2
Answers
For change the default source IModelBinder in ASP.NET, can use the [ModelBinder] attribute on your Id type. By applying this you can specify the default binding source for your model. Model Binding in ASP.NET Core
If don’t understand from this source, see below example:
After applying this your controller action can be simplified as follows:
ASP.NET will automatically bind the Id parameter from the route by default, as specified in the [ModelBinder] attribute.
Hope help you! :))
To change the default binding source for your custom
Id<TEntity>
struct without using annotations on theId
parameter itself, you can customize the behavior in your customIModelBinderProvider
andIModelBinder
. By default, yourId<TEntity>
struct is being treated as a complex type, which results in the[FromBody]
binding source being used. To change this behavior, you’ll need to specify a custom model binder for yourId<TEntity>
type and set the default binding source there.Here’s how you can achieve this:
Id<TEntity>
struct:With the above implementation, your
Id<TEntity>
struct should now bind from the route by default without needing the[FromRoute]
attribute on the Id parameter in your controller actions.