什么是ModelBinding
ASP.NET MVC中,所有的請求最終都會到達某個Controller中的某個Action並由該Action負責具體的處理和響應。為了能夠正確處理請求,Action的參數(如果有的話),必須在Action執行之前,根據相應的規則,把請求中所包含的數據提取出來並將映射為Action的參數值,這個過程就是ModelBinding。ModelBinding的作用就是為Action提供參數列表。
ModelBinding的好處
- 使代碼變得更加簡潔
- 幫助我們獲取HTTP請求中的數據
- 幫助我們完成必要的數據類型轉換
ASP.NET MVC中ModelBinding的實現過程
ASP.NET MVC中ModelBinding的實現過程比較復雜,這里簡要說明它的總體流程。具體的實現過程可以看蔣金楠的《ASP.NET MVC5框架揭秘》或者看他的博客How ASP.NET MVC Works?,講解很詳細。

- HTTP請求中的數據可能存在於querystring中,也可能在表單中,也有可能是JSON字符串。究竟從哪里獲取數據,這要依賴於參數的描述信息
ParameterDescriptor
ParameterDescriptor
的獲取需要借助於ControllerDescriptor
和ActionDescriptor
,它們分別用來描述Controller和ActionIModelBinderProvider
用於提供合適的ModelBinder對象,我們可以自己實現該接口以獲取自定義的IModelBinder
- ModelBinding的核心是
IModelBinder
,默認實現類是DefaultModelBinder
,我們可以自己實現IModelBinder
接口來擴展ModelBinder IValueProvider
針對不同的數據源提供了數據的訪問機制ValueProviderResult
提供了兩個ConvertTo方法重載以實現向指定目標類型的轉換。- 經過上述一系列的處理獲取最終結果
自定義ModelBinder
自定義Modelbinder只需實現System.Web.Mvc.IModelBinder
接口即可。這里需要注意一點,System.Web.ModelBinding
命名空間下也有一個IModelBinder
接口,不要搞錯了。
public class LessonEditInfoViewModelBinder : IModelBinder { //根據前台傳遞的id值獲取對象 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var idStr = controllerContext.HttpContext.Request["id"] ?? controllerContext.RouteData.Values["id"]?.ToString(); int id = 0; if (!int.TryParse(idStr, out id)) { return null; } var model = new LessonBLL().GetLessonEditInfo(id); return model; } }
然后使用ModelBinderAttribute
進行標注即可:
/* 根據前台傳遞的id值解析出對象數據,Action無需關注對象的獲取,使代碼變得清晰簡潔 */ public ActionResult Edit([ModelBinder(typeof(LessonEditInfoViewModelBinder))]LessonEditInfoViewModel lesson) { if (lesson == null) { //跨控制器的視圖跳轉要使用視圖的路徑+文件名 return View("/Views/Exception/GenericError.cshtml", new ExceptionViewModel { Title = "404", Description = "課程不存在!" }); } return View(lesson); }
如果項目中多處需要使用自定義的ModelBinder,那么再使用ModelBinderAttribute
進行標注就不大合適了。這種情況我們可以使用自定義的ModelBinderProvier。代碼如下:
public class CustomeModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(Type modelType) { if (modelType == typeof(LessonEditInfoViewModel)) { return new LessonEditInfoViewModelBinder(); } return null; } }
然后將自定義的ModelBinderProvider注冊到ASP.NET MVC系統中
public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { ModelBinderProviders.BinderProviders.Insert(0, new CustomeModelBinderProvider()); } }
完成上述兩步之后,就無需使用ModelBuilderAttribute
進行標注了。
除此之外,還可在Global文件中使用使用ModelBinder
類的Binder
屬性來注冊ModelBinderProvider
ModelBinders.Binders.Add(typeof(LessonEditInfoViewModel),new LessonEditInfoViewModelBinder());
不同的ModelBinder提供策略有不同的優先級,具體如下:
- 在參數上使用CustomModelBinderAttribute
- 使用ModelBinderProviders.BinderProviers
- 使用ModelBinders.Binders
- 參數類型上標記CustomModelBinderAttribute
- ASP.NET MVC中提供的DefaultModelBinder
注意,CustomModelBinderAttribute是抽象類,在ASP.NET MVC中有唯一子類ModelBinderAttribute。
參考文章:
Model Binders in ASP.NET MVC
ModelBinder——ASP.NET MVC Model綁定的核心
ASP.NET MVC以ValueProvider為核心的值提供系統
玩轉Asp.net MVC 的八個擴展點
ASP.NET MVC中你必須知道的13個擴展點