[MVC.NET] 使用ModelBinders註冊Model綁定(Model Binding)
對於有在使用MVC開發的人,對於Model Binding應該不陌生,
這裡還是稍微提一下甚麼是Model Binding。
首先頁面的部分固定如下(MVC3)
index.cshtml
@using (Html.BeginForm()) { <div> USER ID: @Html.TextBox("userID")<br /> USER NAME: @Html.TextBox("userName")<br /> <input type="submit" /> </div> }
按下送出後,
先來看一般的Model Binding
HomeController.cs
簡易原始值Model Binding
[HttpPost] public ActionResult Index(string userID, string userName) { user u = new user() { userID = userID, userName = userName }; return View(); }
換成物件的的Model Binding,ASP.NET MVC會自動將相同名稱的對應到物件中。
複雜物件Model Binding
[HttpPost] public ActionResult Index(user u) { //.... return View(); }
那如果Binding成介面的類型呢?
我們做個Iuser介面並讓user類別實做,並將Controller中的Binding換成Iuser
Iuser.cs
public interface Iuser { string userID { get; set; } string userName { get; set; } }
user.cs
public class user : Iuser { public string userID { get; set; } public string userName { get; set; } }
HomeController.cs
[HttpPost] public ActionResult Index(Iuser u) { return View(); }
基本上這樣編譯是可以過的,但是會引發Model發生錯誤,
因為DefaultModelBinder無法知道Iuser 要建立的實體類別到底是甚麼。
解決方式就是要自訂Model Binding程式。
就必須要使用ModelBinders來註冊,並實做IModelBinder類別。
建立一個新的類別實做IModelBinder
userModelBinder.cs
public class userModelBinder : IModelBinder { #region IModelBinder 成員 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { user u = new user() { userID = bindingContext.ValueProvider.GetValue("userID").AttemptedValue, userName = bindingContext.ValueProvider.GetValue("userName").AttemptedValue }; return u; } #endregion }
實做完IModelBinder後,就要向ModelBinders註冊Model囉。
要在Global中Application_Start()進行。
Global.asax.cs
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); //增加userModelBinder ModelBinders.Binders.Add(typeof(Iuser), new userModelBinder()); }
再執行一次已經可以成功取得值囉
只是這樣的做法,是有滿多缺點的拉,這篇只是紀錄如何向ModelBinders增加Model Binding綁定,也就不講究太多了。
這種做法應用於Session取值個人覺得也滿不錯的,讓Model Binding固定會從Session中取得想要的值,
稍微改一下程式
userModelBinder.cs
public class userModelBinder : IModelBinder { #region IModelBinder 成員 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { return controllerContext.HttpContext.Session["userinfo"] as user; } #endregion }
接著在Global中模擬將值放入Session
Global.asax.cs
protected void Session_Start(object sender, EventArgs e) { HttpContext.Current.Session["userinfo"] = new user() { userID = "stevenTEST",userName="阿鬼TEST" }; }
這樣每次回到Controller端的時候,都會由Session中取值傳入Model Binding中。還滿方便的喔~