[MVC.NET] 使用ModelBinders註冊Model綁定(Model Binding)

[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>
 }

 

image

按下送出後,

先來看一般的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 要建立的實體類別到底是甚麼。

image 

解決方式就是要自訂Model Binding程式。

就必須要使用ModelBinders來註冊,並實做IModelBinder類別。

image

 

建立一個新的類別實做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());
        }

再執行一次已經可以成功取得值囉

image

只是這樣的做法,是有滿多缺點的拉,這篇只是紀錄如何向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中。還滿方便的喔~

image