ASP.NET WebAPI 2 中复杂类型的选择性自定义参数绑定

Selective custom parameters binding for complex types in ASP.NET WebAPI 2

好的,所以在深入了解 SO 和其他资源之后,我无法找到满足我的要求的正确解决方案。

假设我有一个像这样的复杂类型:

public class CreateItemRequest : AuthenticatedRequest
{
    public Item Item { get; set; }
}

public abstract class AuthenticatedRequest
{
    public string AuthToken { get; set; }
}

为此控制器操作:

[HttpPost]
[Route("")]
public IHttpActionResult CreateItem(CreateItemRequest request)
{
   _aCoolInjectedBusinessLayer.CreateItem(request);
}

我只需要为来自自定义 header 请求的 属性 AuthToken 自定义参数绑定。继承中的所有其他属性应由默认 ASP.NET 模型绑定器填充。

如果我使用 IModelBinder 方法,则无法有选择地只填充一些属性。全有或全无。

您可以通过 HttpParameterBinding 的自定义实现来实现您所需要的。它将基于默认实现来执行所有绑定,但会额外检查自定义 header 并填充 AuthToken 属性。这是工作实施:

public class AuthRequestBinding : HttpParameterBinding
{
    private readonly HttpParameterDescriptor paramDescriptor;

    public AuthRequestBinding(HttpParameterDescriptor descriptor) : base(descriptor)
    {
        paramDescriptor = descriptor;
    }

    public override async Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext,
        CancellationToken cancellationToken)
    {
        var defaultBinder = new FromBodyAttribute().GetBinding(paramDescriptor);
        await defaultBinder.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);

        AuthenticatedRequest authRequest = actionContext.ActionArguments[paramDescriptor.ParameterName] as AuthenticatedRequest;
        if (authRequest != null)
        {
            IEnumerable<string> headerValues;
            if (actionContext.Request.Headers.TryGetValues("Your-Custom-Header-Here", out headerValues))
            {
                authRequest.AuthToken = headerValues.FirstOrDefault();
            }
        }
    }
}

不要忘记在 Web 中注册自定义活页夹 API 配置:

config.ParameterBindingRules.Insert(0, paramDesc =>
{
    if (typeof(AuthenticatedRequest).IsAssignableFrom(paramDesc.ParameterType))
    {
        return new AuthRequestBinding(paramDesc);
    }

    return null;
});