標籤:
ParameterBindingAttribute
在上一篇中重點講了ModelBinderAttribute的使用情境。這一篇詳細的講一下ModelBinder背後的參數綁定原理。
ModelBinderAttribute繼承自ParameterBindingAttribute,從命名上就是可以看出ParameterBindingAttribute是對Action參數進行綁定的一種特性。除了ModelBinderAttribute之外,WebAPI還另外定義了ValueProviderAttribute,FromUriAttribute與FromBodyAttribute三個ParameterBindingAttribute衍生類別。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] public abstract class ParameterBindingAttribute : Attribute { protected ParameterBindingAttribute(); public abstract HttpParameterBinding GetBinding(HttpParameterDescriptor parameter);}
ParameterBindingAttribute只提供了一個GetBinding方法,這個方法返回一個HttpParameterBinding類型對象,HttpParameterBinding是參數綁定過程中的一個核心類,它基本完成了從請求資料讀取到參數綁定的整個過程。
在這裡需要重點關注一下HttpParameterDescriptor,它做作為對參數的一個描述對象,包含了參數的一個資訊(這個參後續還將詳細講解)
HttpParameterBinding
public abstract class HttpParameterBinding { protected HttpParameterBinding(HttpParameterDescriptor descriptor); public HttpParameterDescriptor Descriptor { get; } public virtual string ErrorMessage { get; } public bool IsValid { get; } public virtual bool WillReadBody { get; } public abstract Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken); protected object GetValue(HttpActionContext actionContext); protected void SetValue(HttpActionContext actionContext, object value);}
其中ExecuteBindingAsync方法實現具體的參數綁定。對於來自Uri與Body的資料可通過WillReadBody進行區分,WillReadBody預設為false。
ModelBinderParameterBinding
現在我們回過頭去再看上一篇的Model綁定。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] public class ModelBinderAttribute : ParameterBindingAttribute { public ModelBinderAttribute(); public ModelBinderAttribute(Type binderType); public Type BinderType { get; set; } public string Name { get; set; } public bool SuppressPrefixCheck { get; set; } public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter); public IModelBinder GetModelBinder(HttpConfiguration configuration, Type modelType); public ModelBinderProvider GetModelBinderProvider(HttpConfiguration configuration); public virtual IEnumerable<System.Web.Http.ValueProviders.ValueProviderFactory> GetValueProviderFactories(HttpConfiguration configuration); }
在ModelBinderParameterBinding中定義了一個GetModelBinderProvider方法。ModelBinderProvider中定義一個GetBinder方法用於擷取ModelBinder。
而ModelBinder正是完成Model綁定的基礎類。
ModelBinderAttribute
FromUriAttribute
ValueProviderAttribute
FormatterParameterBinding
對於Body中的資料,WebAPI提供了FormatterParameterBinding進行資料繫結。由於Body可以提供的資料格式不像Uri那樣單一,所以我們Body能夠更加方便的為我們提供複雜的資料結構。FormatterParameterBinding從命名就可以看出來它提供將Body資料還原序列化並綁定到參數的功能。
MediaTypeFormatter
對於不同的請求資料格式,FormatterParameter會根據請求的Conent-Type,提供不同的序列化對象。而這些序列化處理類型都繼承於MediaTypeFormatter。
下面我列舉一下Content-Type與MediaTypeFormatter的對應關係。
Content-Type |
MediaTypeFormatter |
text/xml,application/xml |
XmlMediaTypeFormatter |
text/json,application/json |
MediaTypeFormatter |
application/x-www-form-urlencoded |
FormUrlEncodedMediaTypeFormatter |
application/x-www-form-urlencoded |
JqueryMvcFormUrlEncodedFormatter |
FromBodyAttribute
IActionValueBinder
public interface IActionValueBinder { HttpActionBinding GetBinding(HttpActionDescriptor actionDescriptor); }
綁定入口。
HttpActionBinding
public class HttpActionBinding { public HttpActionBinding(); public HttpActionBinding(HttpActionDescriptor actionDescriptor, HttpParameterBinding[] bindings); public HttpActionDescriptor ActionDescriptor { get; set; } public virtual Task ExecuteBindingAsync(HttpActionContext actionContext, CancellationToken cancellationToken); } }
參數分離。
ASP.NET WebAPI 05 參數綁定