英文:
Change default source for custom `IModelBinder`
问题
我创建了一个强类型的ID,以防止实体A的ID与实体B混合在一起,就像这样:
```csharp
public record struct Id<TEntity>(int Value);
我还创建并注册了一个IModelBinder和一个IModelBinderProvider,以便我可以在我的控制器中有以下签名:
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetById(Id<Product> id);
然而,这有一个问题。虽然int参数默认具有[FromRoute]绑定源,但我的Id结构默认具有[FromBody]绑定源,需要我明确添加属性:
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetById([FromRoute] Id<Product> id);
所以我的问题是,如何在不使用注解(包括在Id上)的情况下从绑定器/提供程序更改默认绑定源?
<details>
<summary>英文:</summary>
I made a strongly typed id to prevent ids from entity A from being mixed with entity B, like so:
```csharp
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)?
答案1
得分: 1
[ApiController] 属性将 绑定源参数推断 应用于控制器:
> 对于未在 DI 容器中注册的复杂类型参数,会推断出 [FromBody]。
在您的示例中,Id<TEntity> 是一个复杂类型,因此在用作控制器参数时会得到 隐含的 [FromBody] 属性。
要覆盖此行为,以 隐含 [FromRoute] 属性,添加一个使用 BindingSource.Path 的类型的 BindingSourceMetadataProvider:
builder.Services.AddControllers(options =>
{
// ...
options.ModelMetadataDetailsProviders.Add(
new BindingSourceMetadataProvider(typeof(Id<>), BindingSource.Path));
});
英文:
The [ApiController] attribute applies binding source parameter inference to a controller:
> [FromBody] is inferred for complex type parameters not registered in the DI Container.
In your example, Id<TEntity> is a complex type, so it gets an implied [FromBody] attribute when used as a controller parameter.
To override this, and imply a [FromRoute] attribute, add a BindingSourceMetadataProvider for the type that uses BindingSource.Path:
builder.Services.AddControllers(options =>
{
// ...
options.ModelMetadataDetailsProviders.Add(
new BindingSourceMetadataProvider(typeof(Id<>), BindingSource.Path));
});
答案2
得分: 0
要更改ASP.NET中默认的IModelBinder,可以在您的Id<TEntity>类型上使用[ModelBinder]属性。通过应用此属性,您可以为模型指定默认绑定源。ASP.NET Core中的模型绑定
如果从这个来源不明白,请参阅下面的示例:
[ModelBinder(BindingSource = BindingSource.Path)]
public record struct Id<TEntity>(int Value);
应用此属性后,您的控制器操作可以简化如下:
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetById(Id<Product> id)
{
// 在这里实现您的操作
}
ASP.NET会根据[ModelBinder]属性中指定的默认设置,自动从路由绑定Id<Product>参数。
希望对您有所帮助! :))
英文:
For change the default source IModelBinder in ASP.NET, can use the [ModelBinder] attribute on your Id<TEntity> 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:
[ModelBinder(BindingSource = BindingSource.Path)]
public record struct Id<TEntity>(int Value);
After applying this your controller action can be simplified as follows:
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetById(Id<Product> id)
{
// Your implementation here
}
ASP.NET will automatically bind the Id<Product> parameter from the route by default, as specified in the [ModelBinder] attribute.
Hope help you! :))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论