邊看邊譯《asp.net mvc 4 in action》(二)


3.2.3 帶視圖模型的強類型視圖

當使用基於Razor的視圖時,視圖默認繼承兩個類型:System.Web.Mvc.WebViewPage或者System.Web.Mvc.WebViewPage<T>。泛型WebViewPage<T>繼承自WebViewPage,但是提供了一些非泛型WebViewPage類里沒有的獨特的補充。

      下面展示了WebViewPage<T>的主干成員定義:

 

清單 3.3

 

public  class WebViewPage<TModel> : WebViewPage
{
public  new AjaxHelper<TModel> Ajax {  getset; }
public  new HtmlHelper<TModel> Html {  getset; }
public  new TModel Model {  get; }
public  new ViewDataDictionary<TModel> ViewData {  getset; }
}

 

除了通過Model屬性在ViewData.Model之上提供了一個強類型包裝器外,WebViewPage<T>類還提供訪問關聯視圖的幫助器對象的強類型版本,AjaxHelper和HtmlHelper。

     要使用強類型視圖,首先你必須確保控制器動作正確設置了ViewData.Model。在清單3.4里,我們獲取所有的留言記錄,顯示在列表頁面,並傳遞個人檔案的整個集合到View方法,此方法封裝了對ViewData.Model屬性的設置。

 

清單 3.4

 

public ActionResult Index()
{
var mostRecentEntries = ( from entry  in _db.Entries
orderby entry.DateAdded descending
select entry).Take( 20);
var model = mostRecentEntries.ToList();
return View(model);
}

 

 

在與這個動作相應的Index視圖里,即使松散類型的WebViewPage類也能使用ViewData.Model屬性。但是這個屬性只是一個object類型,我們需要對它進行轉換以便有效地使用它。作為替代方案,我們能用@model關鍵詞指定模型的類型。

 

@using Guestbook.Models
@model List<GuestbookEntry>

通過用@model關鍵詞指定模型的類型,我們的視圖現在繼承自WebViewPage<T>而不是WebViewPage,我們有了一個強類型視圖。我們也用@using關鍵詞導入名字空間。在下一部分,我們將看到如何使用模型對象在視圖里顯示信息。

 

3.2.4

一般要在視圖里顯示信息,你可以使用HtmlHelper對象幫助獲得視圖模型以生成HTML。考慮下下面的清單,我們呈現了一個完整的留言板記錄。

清單 3.5

 

< h2 >Guestbook Entry </ h2 >
< dl >
< dt >Name: </ dt >
< dd >@Model.Name </ dd >
< dt >Date Added: </ dt >
< dd >@Model.DateAdded </ dd >
< dt >Message: </ dt >
< dd >@Model.Message </ dd >
</ dl >
< p >
@{
bool hasPermission =
(bool) ViewData["hasPermission"];
}
@if (hasPermission)
{
@Html.ActionLink("Edit", "Edit",
new {id = Model.Id})
}
@Html.ActionLink("Back to Entries", "Index")
</ p >

在這里,我們顯示在模型里傳遞的留言板詳細信息。接着,我們用Razor多行代碼語句從ViewData中獲取”hasPermission“的值。Razor多行語句用at符號后跟一個大括號來開始一個代碼塊:@{。最后,我們用一個Razor的if塊來有條件的顯示Edit鏈接。因為當在屏幕上顯示未編碼的用戶輸入時有可能遭到各種腳本攻擊,所以數據在呈現到屏幕以前默認是被自動編碼的。為了顯示未編碼的信息,我們可以使用Html.Raw方法強制顯示原生文本。

      在登錄頁面,我們用一個視圖模型對象代表完整的表單,就像下面清單顯示的:

清單 3.6

 

public  class LogOnModel
{
[Required]
[Display(Name =  " User name ")]
public  string UserName {  getset; }
[Required]
[DataType(DataType.Password)]
[Display(Name =  " Password ")]
public  string Password {  getset; }
[Display(Name =  " Remember me? ")]
public  bool RememberMe {  getset; }
}

LogOnModel類很簡單,只包括必須的屬性。你在這里看到的特性是數據注解,關於它們更多的內容會在第4章學到。對於每一個屬性在登錄頁面都會顯示一個輸入元素,如圖3.2所示。

圖3.2 登錄頁

 

因為我們為登陸頁選擇了強類型視圖,我們能用內建的幫助器來為每一個輸入元素繪制出HTML。取代松散的綁定到代表動作參數的字符串,我們能利用基於表達式的HtmlHelper擴展創建各種類型的輸入元素,如下:

清單 3.7

 

@using (Html.BeginForm()) {
@Html.ValidationSummary(true,
"Account creation was unsuccessful. " +
"Please correct the errors and try again.")
< div >
< fieldset >
< legend >Account Information </ legend >
< div  class ="editor-label" >
@Html.LabelFor(m => m.UserName)
</ div >
< div  class ="editor-field" >
@Html.TextBoxFor(m => m.UserName)
@Html.ValidationMessageFor(
m => m.UserName)
</ div >
< div  class ="editor-label" >
@Html.LabelFor(m => m.Email)
</ div >
< div  class ="editor-field" >
@Html.TextBoxFor(m => m.Email)
@Html.ValidationMessageFor(m => m.Email)
</ div >
< div  class ="editor-label" >
@Html.LabelFor(m => m.Password)
</ div >
< div  class ="editor-field" >
@Html.PasswordFor(m => m.Password)
@Html.ValidationMessageFor(m => m.Password)
</ div >
< div  class ="editor-label" >
@Html.LabelFor(m => m.ConfirmPassword)
</ div >
< div  class ="editor-field" >
@Html.PasswordFor(m => m.ConfirmPassword)
@Html.ValidationMessageFor(m => m.ConfirmPassword)
</ div >
< p >
< input  type ="submit"  value ="Register"   />
</ p >
</ fieldset >
</ div >
}

在先前的清單里,我們為強類型視圖頁面使用了幾個HtmlHelper的擴展方法,這些方法分別針對標簽,輸入框和驗證信息。取代用松散類型的字符串代表屬性,在asp.net mvc 1里就是這樣使用( @Html.TextBox("UserName")),這些幫助器方法利用c# 3.5的表達式來生成HTML。因為這些生成的HTML元素需要與對象中的屬性匹配,所以只適合用於原生的類型和與表達式一起使用的對象。

     在清單3.7里Html.LabelFor和Html.TextBoxFor方法為UserNam屬性產生HTML:

清單3.8

< label  for ="UserName" >User name </ label >
< input  id ="UserName"  name ="UserName"  type ="text"  value =""   />

為了讓我們的頁面通過可訪問性驗證,每一個輸入元素(如清單3.8的第二行)需要包含一個相應的標簽元素(如第一行)。因為我們的標簽和輸入元素都是用表達式生成的,所以我們不再擔心標簽和輸入名稱硬編碼的問題。

      表格3.1列出了用於強類型視圖的HtmlHelper的各種擴展方法。

 

表格3.1

  •  DisplayFor
  • DisplayTextFor
  • EditorFor
  • CheckBoxFor
  • DropDownListFor
  • HiddenFor
  • LabelFor
  • ListBoxFor
  • PasswordFor
  • RadioButtonFor
  • TextAreaFor
  • TextBoxFor
  • ValidateFor
  • ValidationMessageFor

由於我們的表單是用強類型視圖生成的,我們可以在設計表單post的動作上利用這一點。不用枚舉每個輸入域的值作為動作方法的參數,我們可以把所有的參數都綁定到與呈現視圖同一個的視圖模型上,如下所示。

清單3.9

 

public ActionResult LogOn(LogOnModel model,  string returnUrl)
{
//  Action method body here
...
}

正如你看見的,LogOn動作方法使用單個LogOnModel對象,以及要返回的URL,而不是為表單里的每個輸入元素用一個方法參數。

     HtmlHelper擴展可能是強大的,但如果只依賴這些擴展產生HTML,在視圖里仍然會引入了相當多的重復。例如,如果每個輸入元素需要一個相應的標簽,為什么不總是包括它呢?每個用戶界面是不同的,所以MVC團隊不能預知每個人所用的輸入和標簽元素的布局。雖然每個輸入元素都應該有一個標簽,現有的創建輸入元素的輔助方法不適合包括標簽元素。作為替代方案,我們可以利用在asp.net mvc 2里介紹的功能——模版——用一種標准化的方式產生HTML。


免責聲明!

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



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