ASP.NET Web Api 2发布请求来自Uri和From Body

问题描述 投票:1回答:2

我有一个ASP.NET Web Api 2端点,意味着由不同的客户端使用。端点应接受来自正文和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
2个回答
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标头以查明请求是否包含http正文。如果是,我们将模型与正文绑定。否则,模型将从Url绑定。

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

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

这是应该添加到WebApiConfig.Register()方法的活页夹注册。我们检查action参数是否用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)
{
    //  ...
}

2
投票

我能够通过让我的Controller Action获得两个参数来解决它。我的数据类型的两个参数 - 一个带有[FromUri]属性,另一个带有:

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

}

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

© www.soinside.com 2019 - 2024. All rights reserved.