在使用第三方接口時,有時候會看到接口同時支持GET和POST,當時想想webapi有AcceptVerbs特性,沒有細想便想當然肯定會支持,后來項目中需要用到,當時在沒有參數傳入下確實支持,直到早幾天,碰到需要傳入參數的接口.
還是按照原來的思路去做,當寫參數時時用FromUri還是FromBody,這時問題來了,默認webapi是不能同時支持GET和POST時[當需接受多個參數時]。想了想web api與asp.net mvc接受參數綁定是不同的。
經過一些搜索有了一些啟發,找到了如下面的代碼。
public class FromUriOrBodyParameterBinding : HttpParameterBinding
{
HttpParameterBinding _defaultUriBinding;
HttpParameterBinding _defaultFormatterBinding;
public FromUriOrBodyParameterBinding(HttpParameterDescriptor desc)
: base(desc)
{
_defaultUriBinding = new FromUriAttribute().GetBinding(desc);
_defaultFormatterBinding = new FromBodyAttribute().GetBinding(desc);
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (actionContext.Request.Content != null && actionContext.Request.Content.Headers.ContentLength > 0)
{
return _defaultFormatterBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);
}
else
{
return _defaultUriBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);
}
}
config.ParameterBindingRules.Insert(0, x =>
{
if (x.ParameterType == typeof(LoginModel))
{
return new FromUriOrBodyParameterBinding(x);
}
return null;
});
到了此處,原理上是支持了。
但是作為程序員肯定對於這種寫法是不能容忍的.
后面想到FromBody特性。於是乎查看webapi源代碼。
翻閱源碼按照FromBody實現的思路,有了下面的代碼。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
public sealed class FromUriOrBodyAttribute : ParameterBindingAttribute
{
public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter)
{
return new FromUriOrBodyParameterBinding(parameter);
}
public class FromUriOrBodyParameterBinding : HttpParameterBinding
{
HttpParameterBinding _defaultUriBinding;
HttpParameterBinding _defaultFormatterBinding;
public FromUriOrBodyParameterBinding(HttpParameterDescriptor desc)
: base(desc)
{
_defaultUriBinding = new FromUriAttribute().GetBinding(desc);
_defaultFormatterBinding = new FromBodyAttribute().GetBinding(desc);
}
public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (actionContext.Request.Content != null && actionContext.Request.Content.Headers.ContentLength > 0)
{
return _defaultFormatterBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);
}
else
{
return _defaultUriBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken);
}
}
}
}
最終用法如下:
[AcceptVerbs("GET","POST")]
public IHttpActionResult Login([FromUriOrBody]LoginModel login)
{
return Ok(login);
}
此處只當記錄一下解決問題的標記。
