【ASP.NET MVC 学习笔记】- 16 Model Binding(模型绑定)
本文參考:http://www.cnblogs.com/willick/p/3424188.html。
1、Model Binding是Http請(qǐng)求和Action方法之間的橋梁,是MVC框架根據(jù)Http請(qǐng)求創(chuàng)建.NET對(duì)象的過(guò)程。它根據(jù)Action方法中的Model對(duì)象的類型創(chuàng)建,NET對(duì)象,并將Http請(qǐng)求數(shù)據(jù)經(jīng)過(guò)轉(zhuǎn)換賦給該對(duì)象。
2、Model Binding是從路由引擎接收和處理Http請(qǐng)求后開(kāi)始的。例如:
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、當(dāng)請(qǐng)求/Home/Index/1時(shí),路由系統(tǒng)把最后一個(gè)片段1賦值給id變量。//2、Action Invoker通過(guò)路由信息得知當(dāng)前請(qǐng)求需要Index這個(gè)Action來(lái)處理;
//3、Action Invoker通過(guò)Model Binder(模型綁定器)來(lái)創(chuàng)建調(diào)用Action方法需要的數(shù)據(jù)對(duì)象;
//4、最后Action Invoker將數(shù)據(jù)對(duì)象賦值給Index這個(gè)Action的參數(shù),再調(diào)用這個(gè)Action完成Http請(qǐng)求。
3、Model Binder實(shí)現(xiàn)了下列接口:
namespace System.Web.Mvc { public interface IModelBinder { object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext); } }?? 在MVC中可以有多個(gè)Model Binder,每個(gè)Binder都負(fù)責(zé)一種或多種類型的Model。當(dāng)Action Invoker調(diào)用Action方法時(shí),它先看這個(gè)Action方法需要的參數(shù),然后為每個(gè)參數(shù)找到和參數(shù)類型對(duì)應(yīng)的Model Binder,然后調(diào)用Model Binder的BindModel方法,BindModel方法再根據(jù)Action方法的參數(shù)名稱從路由信息中獲取參數(shù)值,最后把值提供給Action Invoker,由Action Invoker方法完成Action方法的調(diào)用。
4、Model Binder可以形象的理解為把數(shù)據(jù)綁定到一個(gè)Model的工具。當(dāng)Action Invoker沒(méi)有找到自定義的Model Binder時(shí),就使用系統(tǒng)默認(rèn)的DefaultModelBinder,它通過(guò)以下順序查找要綁定到Model的值,一旦找到就停止查找:
- Request.Form,HTML form 元素提供的值。
- RouteData.Values,通過(guò)應(yīng)用程序路由提供的值。
- Request.QueryString,所請(qǐng)求 URL 的 query string 值。
- Request.Files,客戶端上傳的文件
??? 對(duì)于簡(jiǎn)單類型,DefaultModelBinder會(huì)通過(guò)System.ComponentModel命名空間下的TypeDescriptor類將其轉(zhuǎn)換為和參數(shù)類型相同的類型。若轉(zhuǎn)換失敗則不會(huì)把值綁定到參數(shù)上。
??? Tips:對(duì)于值類型,盡量使用可空類型或可選參數(shù),以免報(bào)錯(cuò)。
5、對(duì)于復(fù)合類型(指不能被TypeConverter轉(zhuǎn)換的類型),DefaultModelBinder類通過(guò)反射獲取該類型所有的公開(kāi)屬性,然后依次進(jìn)行綁定。
6、如果某個(gè)Action方法的參數(shù)的類型是某個(gè)對(duì)象的屬性的類型,此時(shí)需要使用BindAttribute來(lái)告訴DefaultModelBinder只查找特定前綴的的名稱:
public ActionResult DisplayAddress([Bind(Prefix="HomeAddress")]Address address) {return View(address); }??? 需要注意的是使用 Bind 特性指定了前綴后,需要提交的表單元素的 name 屬性必須有該前綴才能被綁定。
??? Bind 特性還有兩個(gè)屬性,Exclude 和?Include。它們可以指定在 Mdoel 的屬性中,Binder?不查找或只查找某個(gè)屬性,即在查找時(shí)要么只包含這個(gè)屬性要么不包含這個(gè)屬性。
7、Model Binder 把請(qǐng)求提交的數(shù)據(jù)綁定到數(shù)組和集合模型上有非常好的支持。
8、當(dāng) action 方法定義了參數(shù)時(shí),Model Binding 的過(guò)程是自動(dòng)的。我們也可以通過(guò)在Action方法中調(diào)用UpdateModel方法來(lái)對(duì)Model Binding的過(guò)程進(jìn)行手動(dòng)控制。示例:
public ActionResult Address() {IList<Address> addresses = new List<Address>();UpdateModel(addresses, new FormValueProvider(ControllerContext));return View(addresses); }??? 示例指定只從Request.Form中查找數(shù)據(jù)。
9、FormValueProvider實(shí)現(xiàn)了IValueProvier接口,是ValueProvider的一種。RouteData.Values、Request.QueryString 和?Request.Files 的 Value Provider 分別是?RouteDataValueProvider、QueryStringValueProvider和HttpFileCollectionValueProvider。
10、還有一種限制Model Binder數(shù)據(jù)來(lái)源的方法,示例:
//用 Action 方法的某個(gè)集合類型的參數(shù)來(lái)指定并存儲(chǔ)從某一個(gè)來(lái)源獲取的數(shù)據(jù),這個(gè)集合類型(示例的 FormCollection) 也是?IValueProvider 接口的一個(gè)實(shí)現(xiàn)。public ActionResult Address(FormCollection formData) {IList<Address> addresses = new List<Address>();UpdateModel(addresses, formData);return View(addresses); }
11、有時(shí)候用戶會(huì)提交一些 和 model 對(duì)象的屬性不匹配的數(shù)據(jù),如不合法的日期格式或給數(shù)值類型提供文本值,這時(shí)候綁定會(huì)出現(xiàn)錯(cuò)誤,Model Binder 會(huì)用 InvalidOperationException 來(lái)表示。可以通過(guò)?Controller.ModelState 屬性找到具體的錯(cuò)誤信息,然后反饋給用戶:
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 屬性來(lái)檢查提交的數(shù)據(jù)是否合法。
13、自定義ValueProvider示例:
//1、實(shí)現(xiàn)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來(lái)實(shí)例化自定義的ValueProvider public class CustomValueProviderFactory : ValueProviderFactory {public override IValueProvider GetValueProvider(ControllerContext controllerContext) {return new CountryValueProvider();} }//3、在Global類的Applcation_Start方法中進(jìn)行注冊(cè) protected void Application_Start() {AreaRegistration.RegisterAllAreas();//通過(guò) ValueProviderFactories.Factories 靜態(tài)集合的 Insert 方法注冊(cè)了我們的 CustomValueProviderFactory 類。//Insert 方法中的 0 參數(shù)保證 Binder 將首先使用自定義的類來(lái)提供值。
//如果我們想在其他 value provider 不能提供值的時(shí)候使用,那么我們可以使用 Add 方法:ValueProviderFactories.Factories.Add(new CustomValueProviderFactory());ValueProviderFactories.Factories.Insert(0, new CustomValueProviderFactory()); }
14、自定義Model Binder示例:
//1、實(shí)現(xiàn)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、注冊(cè) protected void Application_Start() {AreaRegistration.RegisterAllAreas();ModelBinders.Binders.Add(typeof(Address), new AddressBinder()); }?
轉(zhuǎn)載于:https://www.cnblogs.com/wangwust/p/6392587.html
總結(jié)
以上是生活随笔為你收集整理的【ASP.NET MVC 学习笔记】- 16 Model Binding(模型绑定)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 架构之美读书笔记03
- 下一篇: salt常用命令(一)