ASP.NET MVC Model之二模型綁定


Asp.net mvc中的模型綁定,或許大家經常用,但是具體說他是怎么一回事,可能還是會有些陌生,那么,本文就帶你理解模型綁定。為了理解模型綁定,本文會先給出其定義,然后對通過比,來得出使用模型綁定的方便。最后簡單的模擬一下自定義模型綁定,讓大家對模型綁定有進一步的認識。

 一、模型綁定的概念


mvc framework中有一種技術,他就是模型綁定:
使用 被瀏覽器發送的http請求里面數據 來創建.net對象的過程。接下來就讓我們來看看模型綁定的好處。

 二、模型綁定好處 

第二部分,我們通過不使用模型綁定和使用模型綁定的兩種效果的對比,得出模型綁定的優勢。那么接下來先讓我們來模擬一個沒有模型綁定的環境。

2.1沒有模型綁定的環境

  讓我們先來模擬一個沒有模型綁定的環境,主要是讓用戶填寫的信息傳達到Controller中,然后經過加工后顯示到View上(通常情況下我們是得到model后直接把model作為一個模型實體,提交到數據庫了,為了簡單起見,我只是把得到的模型信息顯示出來)。先利用vs2010新建一個mvc3項目,models文件夾中新建一個Person類,代碼如下:
 
        
View Code
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視圖,視圖的代碼如下: 
View Code
 <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,添加如下代碼: 
View Code
        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。代碼如下:
View Code
 <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添加兩個方法:
View Code
        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]標簽,代碼如下:
View Code
        public ActionResult index()
        {
            return View();
        }
        [HttpPost]
        public ActionResult index(int id)
        {
            ViewBag.Info = "編號是" + id;
            return View();
        }
對應的Index視圖的代碼:
View Code
<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屬性值為nullInclude相對的還有一個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,還等什么呢,開始貼代碼: 
View Code
    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中添加如下代碼:

View Code
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文也比較差勁,如果有不對的地方,請大牛們指正!謝謝閱讀!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM