在使用第三方接口時,有時候會看到接口同時支持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); }
此處只當記錄一下解決問題的標記。