Asp.net mvc中的模型綁定,或許大家經常用,但是具體說他是怎么一回事,可能還是會有些陌生,那么,本文就帶你理解模型綁定。為了理解模型綁定,本文會先給出其定義,然后對通過比,來得出使用模型綁定的方便。最后簡單的模擬一下自定義模型綁定,讓大家對模型綁定有進一步的認識。
一、模型綁定的概念
mvc framework中有一種技術,他就是模型綁定:
使用 被瀏覽器發送的http請求里面數據 來創建.net對象的過程。接下來就讓我們來看看模型綁定的好處。
二、模型綁定好處
第二部分,我們通過不使用模型綁定和使用模型綁定的兩種效果的對比,得出模型綁定的優勢。那么接下來先讓我們來模擬一個沒有模型綁定的環境。
2.1沒有模型綁定的環境
讓我們先來模擬一個沒有模型綁定的環境,主要是讓用戶填寫的信息傳達到Controller中,然后經過加工后顯示到View上(通常情況下我們是得到model后直接把model作為一個模型實體,提交到數據庫了,為了簡單起見,我只是把得到的模型信息顯示出來)。先利用vs2010新建一個mvc3項目,在models文件夾中新建一個Person類,代碼如下:

using System.Web.Mvc; using System.ComponentModel.DataAnnotations; public class Person { [Display(Name="編號")] public String Id { get; set; } [Display(Name = "姓:")] public string FirstName { get; set; } [Display(Name = "名:")] public string LastName { get; set; } }
然后在views文件夾里面添加一個Example0視圖,視圖的代碼如下:

<form method="post"/> <table cellpadding="5" cellspacing="0" width="50%"> <tr> <td align="right" nowrap="nowrap" width="15%"> 編號 :</td> <td> <input name="Id" type="text" /></td> </tr> <tr> <td align="right" nowrap="nowrap" width="15%"> 姓 :</td> <td> <input name="FirstName" type="text" /></td> </tr> <tr> <td align="right" nowrap="nowrap" width="15%">名 :</td> <td><input name="LastName" type="text"/></td> </tr> <tr> <td align="left" colspan="2" nowrap="nowrap" width="15%"> <input id="Submit1" type="submit" value="提交" /></td> </tr> <tr> <td align="left" colspan="2"> <strong> @ViewBag.StatusMessage </strong> </td> </tr> </table>
然后在Controllers文件夾里面新建一個HomeController,添加如下代碼:

public ActionResult Example0() { Person p = new Person(); if (Request.Form.Count > 0) { p.Id = Request.Form["Id"]; p.FirstName = Request.Form["FirstName"]; p.LastName = Request.Form["LastName"]; TryUpdateModel(p); ViewBag.StatusMessage = "歡迎您!" + p.FirstName + p.LastName + "您的編號是" + p.Id + "!"; } return View(); }
然后配置路由,使上面的Example0頁面為起始項,運行並填入數據,結果為:
點擊提交按鈕。顯示如下結果:
從Controller的代碼來看,我們主要是使用Request.Form.Count 來判斷是否接收到了值,然后再一一的遍歷我們想要得到的值,最后也算得到了。下面讓我們來看一下使用模型綁定的效果:
2.2使用模型綁定
然后在Views/Home文件夾添加一個Example2.cshtml。代碼如下:

<form method="post"> <table cellpadding="5" cellspacing="0" width="50%"> <tr> <td align="right" nowrap="nowrap" width="15%"> 編號 :</td> <td> <input name="Id" type="text" /></td> </tr> <tr> <td align="right" nowrap="nowrap" width="15%"> 姓 :</td> <td> <input name="FirstName" type="text" /></td> </tr> <tr> <td align="right" nowrap="nowrap" width="15%">名 :</td> <td><input name="LastName" type="text"/></td> </tr> <tr> <td align="left" colspan="2" nowrap="nowrap" width="15%"> <input id="Submit1" type="submit" value="提交" /></td> </tr> <tr> <td align="left" colspan="2"> <strong> @ViewBag.StatusMessage </strong> </td> </tr> </table>
最后在HomeController添加兩個方法:

public ActionResult Example2() { return View(); } [HttpPost] public ActionResult Example2(Person person) { ViewBag.StatusMessage = "歡迎您!" + person.FirstName + person.LastName + "您的編號是" + person.Id + "!"; return View(); }
使Example2作為起始項或輸入指定的URL,然后在文本框里面輸入內容,如下圖
在Example2方法中設置斷點,以觀察person的屬性值,然后點擊按鈕提交:
發現person的各個屬性已經獲得了url中傳過來的值,如下圖:
2.3模型綁定的效果
通過上面的兩種方式的實現,都是將URL中的傳遞的數據包裝成了對象,然后把model的信息顯示到View上面,明顯使用模型綁定會省去很多代碼,特別是在有多個屬性時,這種效果更加明顯,但是要注意的是前台的標簽的name要和我們的model的屬性的名字要一致,否則無法完成綁定。
2.4模型綁定的延伸
在我們給出的模型綁定的概念中,是把URL的請求數據創建成.net對象都算是模型綁定,我們叫上面的函數參數是一個類,叫綁定到類。如果是單純的把其綁定到基礎類型,是不是也符合定義呢?那么就讓我們來看看綁定到基礎類型。
2.4.1綁定到基礎類型
我們先看一個將http請求中的Id綁定到函數的string Id上。在HomeController中新建兩個Index方法,其中帶參數的加上 [HttpPost]標簽,代碼如下:

public ActionResult index() { return View(); } [HttpPost] public ActionResult index(int id) { ViewBag.Info = "編號是" + id; return View(); }
對應的Index視圖的代碼:

<form action="Index" method="post"/> 學號:<input name="id" id =”id” type="text"/> <input id="Submit1" type="submit" value="提交" /> <strong>@ViewBag.Info</strong>
當直接點提交按鈕后,發現程序報錯,如圖
從提示類看錯誤的原因是因為HttpPost的方法接受了一個為空值的Id,所以與int id不能匹配,解決的辦法是使用默認值public ActionResult index(int id=0) 這樣用的另外一個好處是,如果是View中的標簽的name屬性一不小心寫錯了,如把<input name="id1" id="id1" type="text"/>,那么該方法同樣使用默認值,也就是說即使沒有找到與之相匹配的key,也可以使用默認值,雖然沒有到達預期的效果,但不至於報錯。
提交按鈕,會輸出:編號是0.
2.4.2綁定到類的指定屬性
在綁定到類時,或許有的時間我們不想綁定id,那么我們就可以在方法的參數前加一個限制:
public ActionResult Example2([Bind(Include="FirstName,LastName")]Person person)
其他代碼不變,調試結果:
發現Id屬性值為null,Include相對的還有一個Exclude,結果如下:
還有一招更狠的是,假設某個字段為預留字段,在所有的控制器的所有方法都不想被綁定,也防止有些惡意用戶為我們預留字段添加數據,那么可以在model中的類前面加上
[Bind(Exclude="ReservedProperty")]
public class Person {
以上的模型綁定都是使用了默認的綁定,除了上面的兩種可以綁定到的類型,還可以綁定到各種類型,如字典,泛型,以及復雜類型(上一篇中的Address屬性),在此不一一的列舉。但是要記住是“屬性名”要相一致。看到這里,估計你也很想知道,綁定的原理。那就讓我們來看第三部分。
三、把自定義的模型使用在指定的參數上
如果想學會一件事,最好的方法就是實踐一下了,同樣,為了弄清模型綁定的原理,我們就自定義一個模型綁定。之前我們提過,上面的模型綁定都是使用的默認綁定,那么我們肯定想知道一下,即使是默認的綁定,那么是怎么顯示調用的?因為如果知道了顯式的調用方式,那么自定義的就可以按照其調用方法調用了。下面讓我們看一下顯示使用默認模型綁定:
3.1顯式使用默認模型綁定
在看顯式使用默認綁定之前,我們先看一下默認綁定DefaultModelBinder,可以按F12,發現其實現了IModelBinder接口。該接口有一個方法:
// 摘要: // 使用指定的控制器上下文和綁定上下文將模型綁定到一個值。 // // 參數: // controllerContext: // 控制器上下文。 // // bindingContext: // 綁定上下文。 // // 返回結果: // 綁定值。 object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
該方法的返回值即為綁定值。我們先不管那么多,先看一下顯式的調用默認模型綁定看是怎么調用的。其實在每一個參數前多省略了一個[ModelBinder(typeof(DefaultModelBinder))],或者說使用了和他一樣的效果。不相信的話,你可以把上面的代碼放到參數類型的前面,像這樣:
public ActionResult Example2([ModelBinder(typeof(DefaultModelBinder))]Person person)
運行結果,看看是不是和不使用的效果一樣。
知道了顯式的使用默認模型綁定,那么我們是不是可以自定義一個模型綁定也來實現一下呢?
3.2 使用自定義綁定
和默認模型綁定一樣,我們也來實現接口IModelBinder,然后實現其方法BindModel,從參數和返回值的說明來看,ModelBindingContext可能會有些陌生,先放一下,一會單獨說明,回想一下模型綁定,就是使用URL請求數據來創建.net對象,想創建說明樣的對象肯定是我們說了算,請求的參數來自ControllerContext,創建的對象來自於我們的心中,不過也就是返回值的類型了。
所以不影響我們自定義模型綁定,我現在想實現一個把接收到的請求數據轉化成一個Person類,那么是不是就可以實現一個
簡單的自定義綁定,為了區分默認的綁定類的效果還是自定義的效果,我在Person的Id屬性前面加個S,還等什么呢,開始貼代碼:

public class CustomModelBinder:IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { Person person = new Person(); person.Id =”S”+controllerContext.HttpContext.Request["Id"].ToString(); person.FirstName = controllerContext.HttpContext.Request["FirstName"].ToString(); person.LastName = controllerContext.HttpContext.Request["LastName"].ToString(); return person; } }
為了使用自定義的類,我們就在views/Home中添加一個Example3然后在HomeController中添加如下代碼:

public ActionResult Example3() { return View(); } [HttpPost] public ActionResult Example3([ModelBinder(typeof(CustomModelBinder))]Person person)// { ViewBag.StatusMessage = "歡迎您!" + person.FirstName + person.LastName + "您的編號是" + person.Id + "!"; return View(); }
然后把起始頁改為Example3.運行,填入如下數據,點擊提交按鈕。
顯示如下結果:
說明剛剛的自定義綁定已經起作用了,或許默認綁定的過程遠比我們想想的復雜的多,但是至少通過一個自定義綁定,讓我們從思想上有了簡單的認識。最后我們來看一下上面提到有點陌生的那個類ModelBindingContext ,在自定義的綁定內部設斷點,然后填如上面的數據,提交,來看一下bingContext對象,他的ModelName就是我們想要綁定的參數,所以稱為綁定上下文。 其他的具體實現由於其原理比較復雜,不在此文說明。![]()
四、參考文獻
1.http://dotnetslackers.com/articles/aspnet/Understanding-ASP-NET-MVC-Model-Binding.aspx
2.《pro asp.net mvc3 framework》
五、總結
本文從開始列出了模型綁定的定義,然后通過對比了使用模型綁定的兩種效果,並從兩種比較簡單的模型綁定對象說明了默認綁定用法,讓大家對模型綁定有了一個簡單的認識,最后實現了自定義綁定。由於本人菜鳥一枚,E文也比較差勁,如果有不對的地方,請大牛們指正!謝謝閱讀!