ASP.NET MVC 2擴展點之Model Binder
Model Binder在Asp.net MVC中非常簡單。簡單的說就是你控制器中的Action方法需要參數數據;而這些參數數據包含在HTTP請求中,包括表單上的Value和URL中的參數等。而ModelBinder的功能就是將這些個表單上的Value和URL中的參數換成對象,然后將這些對象綁定到Action的參數上面。我簡單的畫了一個圖,看起來會更加直觀。
在asp.net mvc中你可以寫類似下面這樣的代碼:
[HttpPost] public ActionResult Create() { Book book = new Book(); book.Title = Request.Form["Title"]; // ... return View(); }
但是這樣的寫法是非常不可取的,因為代碼不容易閱讀,也不易測試。再看下面的寫法:
[HttpPost] public ActionResult Create(FormCollection values) { Book book = new Book(); book.Title = values["Sex"]; // ... return View(); }
這樣的寫法就可以不用從Request中獲取數據了,這樣能滿足一些情況,比直接從Request中獲取數據要直觀。但是如果在Action需要的數據既要來自表單上的值,又要來自URL的query string。這種情況單單FormCollection是不行的。看下面代碼:
[HttpPost] public ActionResult Create(Book book) { // ... return View(); }
上面的代碼就非常的直觀了,這需要我們的model binder創建一個book對象,然后直接從這個對象的屬性中取值。這個book對象的數據自然也是來自Form和URL。有時候,我們的DefaultModelBinder轉換的能力必經有限,也不夠透明化,一些特殊和復雜的情況就需要我們自定義Model Binder。下面我講講如何去自定義Model Binder。
1、首先我們定義一個Book的實體類:
public class Book { public string Title { get; set; } public string Author { get; set; } public DateTime DatePublished { get; set; } }
2、自定義的model binder需要繼承IModelBinder或者它的子類。數據可以從bindingContext獲取。
public class BookModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var book = (Book)(bindingContext.Model ?? new Book()); book.Title = GetValue<string>(bindingContext, "Title"); book.Author = GetValue<string>(bindingContext, "Author"); book.DatePublished = GetValue<DateTime>(bindingContext, "DatePublished"); if (String.IsNullOrEmpty(book.Title)) { bindingContext.ModelState.AddModelError("Title", "書名不能為空?"); } return book; } private T GetValue<T>(ModelBindingContext bindingContext, string key) { ValueProviderResult valueResult= bindingContext.ValueProvider.GetValue(key); bindingContext.ModelState.SetModelValue(key, valueResult); return (T)valueResult.ConvertTo(typeof(T)); } }
從上面代碼可以看出,自定義的ModelBinde非常的自由,可以自由的將Form上的一個key對應實體的一個屬性,也可以加入一些驗證的邏輯。當然還可以加入一些其他的自定義邏輯。
3、寫好BookModelBinder之后,我們只需要簡單的注冊一下就行了,在Global.asax添加下面代碼:
ModelBinders.Binders.Add(typeof(Book), new BookModelBinder());
總結:本文簡單介紹了一下Asp.net MVC的Model Binder機制。如果敘述有問題,歡迎指正。