更改自定义 `IModelBinder` 的默认源

huangapple go评论81阅读模式
英文:

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&lt;TEntity&gt;(int Value);

I also created and registered an IModelBinder and a IModelBinderProvider, so that I can have the following signature in my controller:

[HttpGet(&quot;{id}&quot;)]
public async Task&lt;ActionResult&lt;Product&gt;&gt; GetById(Id&lt;Product&gt; 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(&quot;{id}&quot;)]
public async Task&lt;ActionResult&lt;Product&gt;&gt; GetById([FromRoute] Id&lt;Product&gt; 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&lt;TEntity&gt; 是一个复杂类型,因此在用作控制器参数时会得到 隐含的 [FromBody] 属性。

要覆盖此行为,以 隐含 [FromRoute] 属性,添加一个使用 BindingSource.Path 的类型的 BindingSourceMetadataProvider

builder.Services.AddControllers(options =&gt;
{                    
    // ...

    options.ModelMetadataDetailsProviders.Add(
        new BindingSourceMetadataProvider(typeof(Id&lt;&gt;), 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&lt;TEntity&gt; 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 =&gt;
{                    
    // ...

    options.ModelMetadataDetailsProviders.Add(
        new BindingSourceMetadataProvider(typeof(Id&lt;&gt;), BindingSource.Path));
});

答案2

得分: 0

要更改ASP.NET中默认的IModelBinder,可以在您的Id<TEntity>类型上使用[ModelBinder]属性。通过应用此属性,您可以为模型指定默认绑定源。ASP.NET Core中的模型绑定

如果从这个来源不明白,请参阅下面的示例:

[ModelBinder(BindingSource = BindingSource.Path)]
public record struct Id&lt;TEntity&gt;(int Value);

应用此属性后,您的控制器操作可以简化如下:

[HttpGet("{id}")]
public async Task&lt;ActionResult&lt;Product&gt;&gt; GetById(Id&lt;Product&gt; 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&lt;TEntity&gt;(int Value);

After applying this your controller action can be simplified as follows:

[HttpGet(&quot;{id}&quot;)]
public async Task&lt;ActionResult&lt;Product&gt;&gt; GetById(Id&lt;Product&gt; 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! :))

huangapple
  • 本文由 发表于 2023年7月13日 21:02:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76679674.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定