【问题标题】:ASP.NET Web Api 2 post request From Uri and From Body来自 Uri 和 From Body 的 ASP.NET Web Api 2 发布请求
【发布时间】:2018-06-30 11:50:40
【问题描述】:

我有一个 ASP.NET Web Api 2 端点,旨在供不同的客户端使用。端点应该接受来自 body 和 Uri 的发布数据。 所以我的问题是我的 POST 操作是否有可能支持这两种类型的请求并将发布的数据映射到 POST 操作中?

我对这个问题的解决方案是公开两个端点 - 一个支持每个场景(请参阅下面的代码),但我宁愿只有一个端点可以提供给所有客户端。怎么可能?

// The Controller Action when data is posted in the Uri:

// POST: api/PostUri
[HttpPost]
[ActionName("PostUri")]
public Result Post([FromUri]Data data)
{
   // Do something..
}

// The Controller Action when request is posted with data in the Body:

// POST: api/MyController/PostBody
[HttpPost]
[ActionName("PostBody")]
public Result PostBody(Data data)
{
   return Post(data);
}

【问题讨论】:

标签: asp.net-web-api asp.net-web-api2 model-binding


【解决方案1】:

我可以通过让我的 Controller Action 接受两个参数来解决它。我的数据类型的两个参数 - 一个带有 [FromUri] 属性,一个没有:

public Result Post([FromUri]Data fromUri, Data fromBody)
{
    // Check fromUri and its properties
    // Check fromBody and its properties
    ...

}

如果将数据的Request放在body中,数据将绑定到fromBody参数。如果Request 数据在URI 中,那么它们将使用[FromUri] 属性绑定到fromUri 参数。

【讨论】:

    【解决方案2】:

    您可以通过自定义实现 HttpParameterBinding 来实现您的目标。这是这种活页夹的工作示例:

    public class UriOrBodyParameterBinding : HttpParameterBinding
    {
        private readonly HttpParameterDescriptor paramDescriptor;
    
        public UriOrBodyParameterBinding(HttpParameterDescriptor descriptor) : base(descriptor)
        {
            paramDescriptor = descriptor;
        }
    
        public override async Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext,
            CancellationToken cancellationToken)
        {
            HttpParameterBinding binding = actionContext.Request.Content.Headers.ContentLength > 0
                ? new FromBodyAttribute().GetBinding(paramDescriptor)
                : new FromUriAttribute().GetBinding(paramDescriptor);
    
            await binding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);
        }
    }
    

    我们检查Content-Length HTTP header 来判断请求是否包含http body。如果是,我们从主体绑定模型。否则模型是从 Url 绑定的。

    您还应该添加自定义属性来标记将使用此自定义绑定器的操作参数:

    [AttributeUsage(AttributeTargets.Parameter)]
    public sealed class FromUriOrBodyAttribute : Attribute
    {
    }
    

    这里是应添加到WebApiConfig.Register() 方法的活页夹注册。我们检查动作参数是否标记为FromUriOrBodyAttribute,并在这种情况下使用我们的自定义绑定器:

    config.ParameterBindingRules.Insert(0, paramDesc =>
    {
        if (paramDesc.GetCustomAttributes<FromUriOrBodyAttribute>().Any())
        {
            return new UriOrBodyParameterBinding(paramDesc);
        }
    
        return null;
    });
    

    现在您可以使用一个 Post 操作来绑定来自请求正文或 Url 的模型:

    [HttpPost]
    public void Post([FromUriOrBody] Data data)
    {
        //  ...
    }
    

    【讨论】:

    • 在我看来,对于一项简单的任务来说,这需要做很多工作!
    • 从 body 和 Uri 参数绑定模型不是一个很常见的任务。这就是 ASP.NET 框架不支持开箱即用的原因。然而,正如我所展示的,它足够灵活并提供了可扩展点以使其成为可能。至于它所需的代码量 - 它似乎并不太复杂,并且基于现有的活页夹。是否使用它取决于您,但我怀疑是否可以用更少的努力做到这一点。
    猜你喜欢
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    相关资源
    最近更新 更多