使用Web API的模型绑定接口属性 [英] Model-bind interface property with Web API

查看:63
本文介绍了使用Web API的模型绑定接口属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个看起来像这样的命令:

I have a command looking like:

public interface ICommand {
    // Just a marker interface
}

public interface IUserAware {
    Guid UserId { get; set; }
}

public class CreateSomething : ICommand, IUserAware
{
    public string Title { get; set; }

    public Guid UserId { get; set; }
}

REST请求是:

PUT /create HTTP/1.1
UserId: 7da6f9ee-2bfc-70b1-f93c-10c950c8f6b0 // Possible an Auth token and not a userId like here.
Host: localhost:63079
Content-Type: application/json
Cache-Control: no-cache
{
    "title": "This is a test title"
}

我的API控制器动作如下:

I have a API controller action looking:

[HttpPut, Route("create")]
public IHttpActionResult CreateSomething([FromBody]CreateSomething command)
{
    // I would like command.UserId already binded here
}

模型上的 Title 属性用请求的正文填充,但是我想使用请求中的一些值绑定 command.UserId 属性标头(例如,来自身份验证令牌的标头).

The Title property on my model is filled out with the body of the request, but I would like to bind the command.UserId property using some values from the request headers (e.g. from a authentication token).

如何从请求标头值中绑定 IUserAware 的属性,例如一个模型绑定器,而不必为具体的 CreateSomething 类创建绑定器?

How can I bind the property of IUserAware from a request header value, with e.g. a model-binder, without having to create a binder for the concrete class CreateSomething?

我已经尝试了Web API中 IModelBinder 接口的各种组合,但是没有真正的运气.

I've tried various combinations of the IModelBinder interface in Web API, but with no real luck.

使用它也感觉多余:

[HttpPut, Route("create")]
public IHttpActionResult CreateSomething([FromBody]CreateSomething command)
{
    command.UserId = GetUserIdFromTheRequest();
}

或者从控制器上的依赖项获取 UserId 并像上面一样进行设置.

Or getting the UserId from a dependency on the controller and set it like the above.

如何在ASP.NET MVC中完成

在ASP.NET MVC中,可以执行以下操作以使其正常工作:

In ASP.NET MVC it is possible to do the following to get it work:

public class UserAwareModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, System.Type modelType)
    {
        var baseModel = base.CreateModel(controllerContext, bindingContext, modelType);
        var commandModel = baseModel as IUserAware;
        if (commandModel != null) 
        {
             commandModel.UserId = controllerContext.HttpContext.User; // or get it from the HttpContext headers.
        }

        return baseModel;
    }
}

并在启动时将其连接:

ModelBinders.Binders.DefaultBinder = new UserAwareModelBinder();

推荐答案

基于@Todd的最新评论,问题的答案是:

Based on @Todd last comment, the answer to the question is:

创建一个 HttpParameterBinding 类:

public class UserAwareHttpParameterBinding : HttpParameterBinding
{
    private readonly HttpParameterBinding _paramaterBinding;
    private readonly HttpParameterDescriptor _httpParameterDescriptor;

    public UserAwareHttpParameterBinding(HttpParameterDescriptor descriptor) : base(descriptor)
    {
        _httpParameterDescriptor = descriptor;
        _paramaterBinding = new FromBodyAttribute().GetBinding(descriptor);
    }

    public override async Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        await _paramaterBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);

        var baseModel = actionContext.ActionArguments[_httpParameterDescriptor.ParameterName] as IUserAware;
        if (baseModel != null)
        {
            baseModel.UserId = new Guid("6ed85eb7-e55b-4049-a5de-d977003e020f"); // Or get it form the actionContext.RequestContext!
        }
    }
}

并将其连接到 HttpConfiguration :

configuration.ParameterBindingRules.Insert(0, descriptor => typeof(IUserAware).IsAssignableFrom(descriptor.ParameterType) ? new UserAwareHttpParameterBinding(descriptor) : null);

如果有人知道如何在.NET Core MVC中完成此操作-请对此进行编辑发表或评论.

If anyone know how this is done in .NET Core MVC - please edit this post or comment.

这篇关于使用Web API的模型绑定接口属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆