英文:
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! :))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论