程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> ASP.NET MVC——模型綁定,asp.netmvc模型

ASP.NET MVC——模型綁定,asp.netmvc模型

編輯:關於.NET

ASP.NET MVC——模型綁定,asp.netmvc模型


   這篇文章我們來講講模型綁定(Model Binding),其實在初步了解ASP.NET MVC之後,大家可能都會產生一個疑問,為什麼URL片段最後會轉換為例如int型或者其他類型的參數呢?這裡就不得不說模型綁定了。模型綁定是指,用浏覽器以HTTP請求方式發送的數據來創建.NET對象的過程。每當定義具有參數的動作方法時,一直是在依賴著這種模型綁定過程。

准備項目

    我們先來創建一個MVC項目,名叫MVCModels,並在Models文件夾中創建一個新的類文件Person。

 1 using System;
 2 
 3 namespace MVCModels.Models
 4 {
 5     public class Person
 6     {
 7         public int PersonId { get; set; }
 8         public string FirstName { get; set; }
 9         public string LastName { get; set; }
10         public DateTime BirthDate { get; set; }
11         public Address HomeAddress { get; set; }
12         public Role Role { get; set; }
13     }
14 
15     public class Address
16     {
17         public string Line { get; set; }
18         public string City { get; set; }
19         public string PostalCode { get; set; }
20         public string Country { get; set; }
21     }
22 
23     public enum Role
24     {
25         Admin,
26         User,
27         Guest
28     }
29 }

    另外定義一個Home控制器。

 1 using MVCModels.Models;
 2 using System.Linq;
 3 using System.Web.Mvc;
 4 
 5 namespace MVCModels.Controllers
 6 {
 7     public class HomeController : Controller
 8     {
 9         private Person[] personDate = {
10             new Person { PersonId = 1, FirstName = "Adam", LastName = "Freeman", Role = Role.Admin },
11             new Person { PersonId = 2, FirstName = "Jacqui", LastName = "Griffyth", Role = Role.User },
12             new Person { PersonId = 1, FirstName = "John", LastName = "Smith", Role = Role.Guest },
13         };
14         public ActionResult Index(int id)
15         {
16             Person dataItem = personDate.Where(p => p.PersonId == id).First();
17             return View(dataItem);
18         }
19     }
20 }

    接下來再創建一個視圖文件Index。

@model MVCModels.Models.Person
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Person</h2>
<div>
    <label>ID:</label>
    @Html.DisplayFor(m => m.PersonId)
</div>
<div>
    <label>First Name:</label>
    @Html.DisplayFor(m => m.FirstName)
</div>
<div>
    <label>Last Name:</label>
    @Html.DisplayFor(m => m.LastName)
</div>
<div>
    <label>Role:</label>
    @Html.DisplayFor(m => m.Role)
</div>

理解模型綁定

    模型綁定是HTTP請求與C#方法之間的一個橋梁,它根據 Action 方法中的 Model 類型創建 .NET 對象,並將 HTTP 請求數據經過轉換賦給該對象。當我們啟動項目,並導航到/Home/Index/1,我們會看見圖下:

    當我們請求 /Home/Index/1 URL 時,路由系統便將最後一個片段值 1 賦給了 id 變量。action invoker 通過路由信息知道當前的請求需要 Index action 方法來處理,但它調用 Index action 方法之前必須先拿到該方法參數的值。 默認的動作調用器ControllerActionInvoker,要依靠模型綁定器來生成調用動作所需要的的數據對象,模型綁定器由IModelBinder接口所定義。在本例中,動作調用器會檢查Index方法,並發現它具有一個int型參數,於是會查找負責int值綁定的綁定器,並調用它的BindModel方法。

使用默認模型綁定器

    雖然應用程序可以自定義模型綁定器,但是大多數情況下還是依靠內建的綁定器類DefaultModelBinder。當動作調用器找不到綁定某個類型的自定義綁定器時,就會使用這個默認的模型綁定器,默認情況下,這個模型綁定器會搜索四個位置。如下表所示:

DefaultModelBinder類查找參數數據的順序 源 描述 Request.From 由用戶在HTML的表單元素中提供值 RouteData.Values 用應用程序路由獲得的值 Request.QueryString 包含在請求URL中的查詢字符串部分的數據 Request.Files 請求中上傳的文件

    這些位置將被依次搜索,在本例中,DefaultModelBinder會為id參數查找以下的一個值:

    1.Request.Form["id"]

    2.RouteData.Values["id"]

    3.Request.QueryString["id"]

    4.Request.Files["id"]

綁定簡單類型

    處理簡單參數類型時,DefaultModelBinder會使用System.ComponentModel.TypeDescriptor類,講請求數據獲得的字符參數值轉換為參數類型,如果無法轉換,那麼DefaultModelBinder便不能綁定到Model。比如訪問/Home/Index/apple,便會出現如圖所示:

    默認模型綁定器看到需要的是int值,如果視圖將URL中提供的apple值轉換為int型,就會出錯,此時我們可以修改代碼,為參數提供一個默認值,這樣當默認綁定器無法轉換時也不會出錯了。

1 ...  
2 public ActionResult Index(int id = 1)
3 {
4     Person dataItem = personDate.Where(p => p.PersonId == id).First();
5     return View(dataItem);
6 }

綁定復雜類型

     當動作方法參數是符合類型時(即不能用TypeConverter類進行轉換的屬性),DefaultModelBinder類將用反射類獲取public屬性集。好的,我們現在來修改代碼。

 1 using MVCModels.Models;
 2 using System.Linq;
 3 using System.Web.Mvc;
 4 
 5 namespace MVCModels.Controllers
 6 {
 7     public class HomeController : Controller
 8     {
 9         private Person[] personDate = {
10             new Person { PersonId = 1, FirstName = "Adam", LastName = "Freeman", Role = Role.Admin },
11             new Person { PersonId = 2, FirstName = "Jacqui", LastName = "Griffyth", Role = Role.User },
12             new Person { PersonId = 1, FirstName = "John", LastName = "Smith", Role = Role.Guest },
13         };
14         public ActionResult Index(int id = 1)
15         {
16             Person dataItem = personDate.Where(p => p.PersonId == id).First();
17             return View(dataItem);
18         }
19         public ActionResult CreatePerson()
20         {
21             return View(new Person());
22         }
23         [HttpPost]
24         public ActionResult CreatePerson(Person model)
25         {
26             return View("Index", model);
27         }
28     }
29 }

    另外創建一個CreatePerson視圖。

 1 @model MVCModels.Models.Person
 2 @{
 3     ViewBag.Title = "CreatePerson";
 4     Layout = "~/Views/Shared/_Layout.cshtml";
 5 }
 6 
 7 <h2>CreatePerson</h2>
 8 @using (Html.BeginForm())
 9 {
10     <div>
11         <label>
12             @Html.LabelFor(m => m.PersonId)
13             @Html.EditorFor(m => m.PersonId)
14         </label>
15     </div>
16     <div>
17         <label>
18             @Html.LabelFor(m => m.FirstName)
19             @Html.EditorFor(m => m.FirstName)
20         </label>
21     </div>
22     <div>
23         <label>
24             @Html.LabelFor(m => m.LastName)
25             @Html.EditorFor(m => m.LastName)
26         </label>
27     </div>
28     <div>
29         <label>
30             @Html.LabelFor(m => m.Role)
31             @Html.EditorFor(m => m.Role)
32         </label>
33     </div>
34     <button type="submit">Submit</button>
35 }

    在表單回遞給CreatePerson方法時,默認綁定器發現動作方法需要一個Person對象,便會依次處理每個屬性。綁定器會從請求中找到每一個值。如果一個屬性需要另一個復合類型時,那麼該過程會重復執行。例如本例中,Person類的HomeAddress屬性是Address類型,在為Line屬性查找值時,模型綁定器查找的是HomeAddress.Line的值,即模型對象的屬性名(HomeAddress)與屬性類型(Address)的屬性名(Line)的組合。

Bind特性

    我們還可以用bind特性為 Address 類型的參數綁定 Person 對象中的 HomeAddress 屬性值,例如這樣:

 

1 public ActionResult DisplayAddress([Bind(Prefix="HomeAddress")]Address address) 
2 {
3     return View(address);
4 }

 

    DisplayAddress action 方法的參數類型 Address 不一定必須是 Person 的 HomeAddress 屬性的類型,它可以是其他類型,只要該類型中含有City

或 Country 同名的屬性就都會被綁定到。不過,要注意的是,使用 Bind 特性指定了前綴後,需要提交的表單元素的 name 屬性必須有該前綴才能被綁定。Bind 特性還有兩個屬性,Exclude 和 Include。它們可以指定在 Mdoel 的屬性中,Binder 不查找或只查找某個屬性,即在查找時要麼只包含這個屬性要麼不包含這個屬性。如下面的 action 方法:

1 public ActionResult DisplayAddress([Bind(Prefix = "HomeAddress", Exclude = "Country")]Address address) 
2 {
3     return View(address);
4 }

這時 Binder 在綁定時不會對 Address 這個 Model 的 Country 屬性綁定值。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved