ControllerContextweb
封裝有了與指定的 RouteBase 和 ControllerBase 實例匹配的 HTTP 請求的信息。 mvc
2.1相關說明ide
http請求中的參數綁定到Model,是由實現了IModelBinder的類來完成的。咱們稱這樣的類叫作Model綁定者ui
using System; namespace System.Web.Mvc { /// <summary>Defines the methods that are required for a model binder.</summary> public interface IModelBinder { /// <summary>Binds the model to a value by using the specified controller context and binding context.</summary> /// <returns>The bound value.</returns> /// <param name="controllerContext">The controller context.</param> /// <param name="bindingContext">The binding context.</param> object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); } }
2.2Model綁定者實現綁定的途徑this
1)直接在參數上綁定spa
using System; using System.Web; using System.Web.Mvc; namespace MVC_ST_2.Controllers { public class Person { public string Name { get; set; } public int Age { get; set; } } public class PersonModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { HttpRequestBase request = controllerContext.HttpContext.Request; var p = new Person(); p.Name = request["Name"]; p.Age =int.Parse( request["Age"]); return p; } } public class HomeController : Controller { //經過參數標記 public ActionResult Index([ModelBinder(typeof(PersonModelBinder))] Person p) { return View(); } public ActionResult Index2(Person p) { return View(); } } }
2)在model上加標記code
[ModelBinder(typeof(PersonModelBinder))] public class Person { public string Name { get; set; } public int Age { get; set; } }
3)ModelBinders.Binders中註冊orm
protected void Application_Start() { ModelBinders.Binders[typeof(Person)] = new PersonModelBinder(); }
2.3 Action中是如何調用綁定者的?htm
如下是
private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor) { return parameterDescriptor.BindingInfo.Binder ?? this.Binders.GetBinder(parameterDescriptor.ParameterType); }
說明:經過參數標記的方式優先,若是沒有則使用this.Binders.GetBinder(parameterDescriptor.ParameterType);
this.Binders的定義
protected internal ModelBinderDictionary Binders { get { if (this._binders == null) { this._binders = ModelBinders.Binders; } return this._binders; } set { this._binders = value; } }
從上圖能夠看出,最終的綁定操做交給了ModelBinderDictionary(注意了,下面會接着講)
正好咱們回到前兩章講的ControllerActionInvoker,其中的參數綁定賦值過程GetParameterValues,如何獲取的過程即綁定的過程
protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) { Type parameterType = parameterDescriptor.ParameterType; IModelBinder modelBinder = this.GetModelBinder(parameterDescriptor); IValueProvider valueProvider = controllerContext.Controller.ValueProvider; string modelName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName; Predicate<string> propertyFilter = ControllerActionInvoker.GetPropertyFilter(parameterDescriptor); ModelBindingContext bindingContext = new ModelBindingContext { FallbackToEmptyPrefix = parameterDescriptor.BindingInfo.Prefix == null, ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType), ModelName = modelName, ModelState = controllerContext.Controller.ViewData.ModelState, PropertyFilter = propertyFilter, ValueProvider = valueProvider }; object obj = modelBinder.BindModel(controllerContext, bindingContext); return obj ?? parameterDescriptor.DefaultValue; }
private IModelBinder GetModelBinder(ParameterDescriptor parameterDescriptor) { return parameterDescriptor.BindingInfo.Binder ?? this.Binders.GetBinder(parameterDescriptor.ParameterType); }
this.Binders 其類型正好是ModelBinderDictionary(上面提到過),他的方法以下
public IModelBinder GetBinder(Type modelType) { return this.GetBinder(modelType, true); } /// <summary>Retrieves the model binder for the specified type or retrieves the default model binder.</summary> /// <returns>The model binder.</returns> /// <param name="modelType">The type of the model to retrieve.</param> /// <param name="fallbackToDefault">true to retrieve the default model binder.</param> /// <exception cref="T:System.ArgumentNullException">The <paramref name="modelType" /> parameter is null.</exception> public virtual IModelBinder GetBinder(Type modelType, bool fallbackToDefault) { if (modelType == null) { throw new ArgumentNullException("modelType"); } return this.GetBinder(modelType, fallbackToDefault ? this.DefaultBinder : null);
//this.DefaultBinder 是下一章咱們須要講的內容。也是整個MVC核心的默認的綁定者
} private IModelBinder GetBinder(Type modelType, IModelBinder fallbackBinder) { IModelBinder modelBinder = this._modelBinderProviders.GetBinder(modelType); if (modelBinder != null) { return modelBinder; } if (this._innerDictionary.TryGetValue(modelType, out modelBinder)) { return modelBinder; } modelBinder = ModelBinders.GetBinderFromAttributes(modelType, () => string.Format(CultureInfo.CurrentCulture, MvcResources.ModelBinderDictionary_MultipleAttributes, new object[] { modelType.FullName })); return modelBinder ?? fallbackBinder;//DefaultBinder 不少狀況下,前面的幾個if都不會執行,因此使用系統默認的綁定者 }