【ASP.NET MVC 学习笔记】- 16 Model Binding(模型绑定)
本文參考:http://www.cnblogs.com/willick/p/3424188.html。
1、Model Binding是Http請求和Action方法之間的橋梁,是MVC框架根據Http請求創建.NET對象的過程。它根據Action方法中的Model對象的類型創建,NET對象,并將Http請求數據經過轉換賦給該對象。
2、Model Binding是從路由引擎接收和處理Http請求后開始的。例如:
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }//1、當請求/Home/Index/1時,路由系統把最后一個片段1賦值給id變量。//2、Action Invoker通過路由信息得知當前請求需要Index這個Action來處理;
//3、Action Invoker通過Model Binder(模型綁定器)來創建調用Action方法需要的數據對象;
//4、最后Action Invoker將數據對象賦值給Index這個Action的參數,再調用這個Action完成Http請求。
3、Model Binder實現了下列接口:
namespace System.Web.Mvc { public interface IModelBinder { object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); } }?? 在MVC中可以有多個Model Binder,每個Binder都負責一種或多種類型的Model。當Action Invoker調用Action方法時,它先看這個Action方法需要的參數,然后為每個參數找到和參數類型對應的Model Binder,然后調用Model Binder的BindModel方法,BindModel方法再根據Action方法的參數名稱從路由信息中獲取參數值,最后把值提供給Action Invoker,由Action Invoker方法完成Action方法的調用。
4、Model Binder可以形象的理解為把數據綁定到一個Model的工具。當Action Invoker沒有找到自定義的Model Binder時,就使用系統默認的DefaultModelBinder,它通過以下順序查找要綁定到Model的值,一旦找到就停止查找:
- Request.Form,HTML form 元素提供的值。
- RouteData.Values,通過應用程序路由提供的值。
- Request.QueryString,所請求 URL 的 query string 值。
- Request.Files,客戶端上傳的文件
??? 對于簡單類型,DefaultModelBinder會通過System.ComponentModel命名空間下的TypeDescriptor類將其轉換為和參數類型相同的類型。若轉換失敗則不會把值綁定到參數上。
??? Tips:對于值類型,盡量使用可空類型或可選參數,以免報錯。
5、對于復合類型(指不能被TypeConverter轉換的類型),DefaultModelBinder類通過反射獲取該類型所有的公開屬性,然后依次進行綁定。
6、如果某個Action方法的參數的類型是某個對象的屬性的類型,此時需要使用BindAttribute來告訴DefaultModelBinder只查找特定前綴的的名稱:
public ActionResult DisplayAddress([Bind(Prefix="HomeAddress")]Address address) {return View(address); }??? 需要注意的是使用 Bind 特性指定了前綴后,需要提交的表單元素的 name 屬性必須有該前綴才能被綁定。
??? Bind 特性還有兩個屬性,Exclude 和?Include。它們可以指定在 Mdoel 的屬性中,Binder?不查找或只查找某個屬性,即在查找時要么只包含這個屬性要么不包含這個屬性。
7、Model Binder 把請求提交的數據綁定到數組和集合模型上有非常好的支持。
8、當 action 方法定義了參數時,Model Binding 的過程是自動的。我們也可以通過在Action方法中調用UpdateModel方法來對Model Binding的過程進行手動控制。示例:
public ActionResult Address() {IList<Address> addresses = new List<Address>();UpdateModel(addresses, new FormValueProvider(ControllerContext));return View(addresses); }??? 示例指定只從Request.Form中查找數據。
9、FormValueProvider實現了IValueProvier接口,是ValueProvider的一種。RouteData.Values、Request.QueryString 和?Request.Files 的 Value Provider 分別是?RouteDataValueProvider、QueryStringValueProvider和HttpFileCollectionValueProvider。
10、還有一種限制Model Binder數據來源的方法,示例:
//用 Action 方法的某個集合類型的參數來指定并存儲從某一個來源獲取的數據,這個集合類型(示例的 FormCollection) 也是?IValueProvider 接口的一個實現。public ActionResult Address(FormCollection formData) {IList<Address> addresses = new List<Address>();UpdateModel(addresses, formData);return View(addresses); }
11、有時候用戶會提交一些 和 model 對象的屬性不匹配的數據,如不合法的日期格式或給數值類型提供文本值,這時候綁定會出現錯誤,Model Binder 會用 InvalidOperationException 來表示。可以通過?Controller.ModelState 屬性找到具體的錯誤信息,然后反饋給用戶:
public ActionResult Address(FormCollection formData) {IList<Address> addresses = new List<Address>();try {UpdateModel(addresses, formData);}catch (InvalidOperationException ex) {var allErrors = ModelState.Values.SelectMany(v => v.Errors);// do something with allErrors and provide feedback to user }return View(addresses); }12、可以用?ModelState.IsValid 屬性來檢查提交的數據是否合法。
13、自定義ValueProvider示例:
//1、實現IValueProvier接口 public class CountryValueProvider : IValueProvider {public bool ContainsPrefix(string prefix){return prefix.ToLower().IndexOf("country") > -1;}public ValueProviderResult GetValue(string key) {if (ContainsPrefix(key))return new ValueProviderResult("China", "China", CultureInfo.InvariantCulture);elsereturn null;} }//2、自定義ValueProviderFactory來實例化自定義的ValueProvider public class CustomValueProviderFactory : ValueProviderFactory {public override IValueProvider GetValueProvider(ControllerContext controllerContext) {return new CountryValueProvider();} }//3、在Global類的Applcation_Start方法中進行注冊 protected void Application_Start() {AreaRegistration.RegisterAllAreas();//通過 ValueProviderFactories.Factories 靜態集合的 Insert 方法注冊了我們的 CustomValueProviderFactory 類。//Insert 方法中的 0 參數保證 Binder 將首先使用自定義的類來提供值。
//如果我們想在其他 value provider 不能提供值的時候使用,那么我們可以使用 Add 方法:ValueProviderFactories.Factories.Add(new CustomValueProviderFactory());ValueProviderFactories.Factories.Insert(0, new CustomValueProviderFactory()); }
14、自定義Model Binder示例:
//1、實現IModelBinder接口 public class AddressBinder : IModelBinder {public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {Address model = (Address)bindingContext.Model ?? new Address();model.City = GetValue(bindingContext, "City");model.Country = GetValue(bindingContext, "Country");return model;}private string GetValue(ModelBindingContext context, string name) {name = (context.ModelName == "" ? "" : context.ModelName + ".") + name;ValueProviderResult result = context.ValueProvider.GetValue(name);if (result == null || result.AttemptedValue == "") return "<Not Specified>";else return (string)result.AttemptedValue;} }//2、注冊 protected void Application_Start() {AreaRegistration.RegisterAllAreas();ModelBinders.Binders.Add(typeof(Address), new AddressBinder()); }?
轉載于:https://www.cnblogs.com/wangwust/p/6392587.html
總結
以上是生活随笔為你收集整理的【ASP.NET MVC 学习笔记】- 16 Model Binding(模型绑定)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 架构之美读书笔记03
- 下一篇: castle windsor学习----