ASPNET MVC4 視圖基礎(Views fundamentals)
--忽然發現我的時間不夠了,但是我還是完成了
本人能力有限,盡量將書中的知識濃縮去講,仔細學過后,然后你再學習其他語言的MVC框架也就大同小異了
本次覆蓋知識點:
- 1. 把數據傳遞給視圖 (Providing data to the view )
- 2. 使用強類型視圖 (Using strongly typed views)
- 3. 使用視圖助手對象 (Understanding view helper objects)
- 4. 用模版開發 (Developing with templates)
視圖(Views)是ASP.NET MVC 應用程序起決定性的一部分--它提供了一個很簡潔的方式,在你的應用程序中,邏輯中涉及到展現頁面的部分分離出來了。在上一章中的我們的Guestbook應用程序中,我們用Razor模版引擎寫了一些簡單的視圖,稍微了解了一點,最后,我們學習了layouts是如何讓你的應用程序中的所有頁面保持一致的風格,結束了上章的課程。
沒有學過的,上章飛機票:點擊開始學習
在本章中,我們將再稍微深入學習一下視圖---我們將會研究一下ASP.NET MVC如何呈現視圖,然后我們再看下把數據傳給視圖的其他不同的一些方法。最后,我們再講一下原來在 ASP.NET MVC 2 中介紹過的一些模版(temlate)特征,為了分析講解這些特征,我們一開始就會在我們的Guestbook應用程序中添加一個編輯頁面。
3.1 視圖介紹
視圖的職責看似簡單。它的目標是與相對應的模型(Model)相關聯,並使用對應的模型來呈現內容。由於控制器(Controller)和相關聯的服務已經處理了所有的業務邏輯,並且把處理后的結果封裝成了模型對象,而視圖只需要知道怎樣把這個模型轉換成HTML來呈現就行了。
盡管這種職責關系的分離可能,對傳統的ASP.NET應用程序編程人員來說編寫造成了麻煩和困擾,但是視圖你還是要編寫的。為了保證你的視圖不會太復雜而很難去維護,所以對於視圖,你還是要小心仔細的,要有意的去設計它.
在我們學習“如何把數據傳遞給視圖”的方法之前,我們先研究一下MVC框架是怎樣把視圖給呈現的。
3.1.1 選擇一個視圖去展示
在上一章里面我們通過調用一個控制器里面的一個action中的一個View方法來讓頁面呈現了。下面這個是我們的GuestbookController控制器里的Create操作:
通過這些代碼, Views/Guestbook/Create.csthml 這個視圖文件就會被呈現。但是在這個應用程序中,MVC框架怎么知道去呈現這個指定的視圖,而不是其他視圖,比如說Index.cshtml的呢?
調用View方法將會返回一個 知道怎么去呈現指定的視圖的ViewResult對象。當調用View的無參數方法時,MVC框架就會認為你要呈現的視圖的名字跟這個方法所在的action(Create)名字一樣。之后,MVC框架的ControllerActionInvoker類就會去調用ViewResult類,然后把呈現頁面的責任轉交給了它。在這個時候,這個框架也會命令ViewEngineCollection去查找要呈現的頁面的位置。(回顧一下上一章的內容。這個視圖引擎默認會在 Views/<Controller Name>目錄和Views/Shared目錄)
視圖引擎
不同的視圖引擎會有它不同的格式去呈現視圖,默認 ASP.NET MVC有兩個視圖引擎-RazorViewEngine和WebFormViewEngine。Razor視圖引擎的格式是cshtml文件或者vbhtml文件,然而WebForm視圖引擎依舊支持老格式的Web Form視圖(aspx頁面和.ascx文件)。以前的ASP.NET MVC版本默認都只包括WebForm視圖引擎。
為什么在ASP.NET MVC3中要引入新的視圖引擎呢?隨着ASP.NET 1.0的發行的開始,Web Form就允許把代碼和標簽寫在一個aspx頁面里面,但是把C#代碼寫在aspx頁面里面,控件的邏輯寫法在通常的開發中嚴重受到阻礙。取而代之的是,開發者們努力去把所有的邏輯放在了頁面的后面(代碼后置)。隨着ASP.NET 的發布,在aspx文件中增加了數據綁定,其他更新的模塊都去適應配合控件開發的模式。
在許多MVC的框架里,視圖開發都鼓勵和要求代碼,直接用標簽去寫(也就是不用控件),由於ASPX視圖引擎在設計時沒有達到這個目標,所以ASP.NET團隊決定去設計一個全新的視圖引擎--把代碼寫在模版里的一種模式。這是一種更智能的引擎,引擎能夠很容易地識別出標簽的開始和結束,而且開發者也不用寫的那么復雜。
當然你也可以用別的第三方的視圖引擎,在第10章,我們就會去看一下現在比較流行的Spark視圖引擎。
3.1.1 重寫View
如果你不想你的視圖名字跟action一樣。你可以使用View的重載方法。例如
return View("New"); 查找路徑 Views/<Controller Name>/New.cshtml和Views/Shared目錄,而不再是action的名字了
你還可以寫路徑,就可以脫離默認的控制名了的路徑限制了
return View(("~/Views/SomeOtherDirectory/New.cshtml");
3.1.2 把數據傳給視圖
我們還是在我們的Guestbook案例上繼續編寫。上篇代碼案例
我們將要講一下把數據傳給視圖的3種不同的方法---ViewDataDictionary,ViewBag,強類型視圖
3.2.1 ViewDataDictionary
把數據傳遞給視圖過去經常使用的最主要的對象就是ViewDataDictionary
和其他MVC框架一樣,ASP.NET MVC也暴露一個集合:可以把更多的model對象傳遞給視圖使用,然后視圖可以利用model里面封裝好的信息來展示信息。
比如說,我們可以拓展我們的guestbook頁面---所有人都可以查看guestbook,但是只有當前登錄的用戶可以編輯guestbook entries(guestbook中的一個實體對象,也就是一條記錄)。為了可以達到這個目的,我們可以通過GuestbookEntry對象,代碼如下:
盡管,這個GuestbookEntry類已經包括了所有我們要在使用GuestbookEntry的頁面上展示的數據了,但是它不包括當前登錄的用戶的信息,或者不能決定視圖是否顯示Edit超鏈接。我們需要給視圖更多的信息,不能僅僅靠GuestbookEntry來做這個決定。我們可以使用ViewDataDictionary來提供更多的信息,代碼如下
public ActionResult Show(int id) {
var entry = _db.Entries.Find(id); //找到該Id的Entries
bool hasPermission = User.Identity.Name == entry.name; //如果登陸人的姓名等於entry錄入人的姓名,就顯示Edit按鈕
ViewData["hasPermission"] = hasPermission;
return View(entry);
}
添加到Controllers/GuestbookController.cs這個文件里面
在Controller里面我們可以直接使用ViewData,因為Controller繼承ControllerBase類,ControllerBase下面有ViewData屬性。我們通過比較GuestbookEntry的name和當前登錄用戶的name是否一樣,然后比較結果放在hasPermission里面,然后視圖那邊查看hasPermission是true還是false來決定是否顯示Edit超鏈接。
添加Show視圖,右鍵action名稱,添加視圖,然后直接點添加
視圖里面代碼如下:
@{
ViewBag.Title = "Show";
}
<p>
@{
bool hasPermission = (bool)ViewData["hasPermission"];
}
@if (hasPermission)
{
@Html.ActionLink("Edit", "Edit", new { id = Model.Id });
}
@Html.ActionLink("返回 Entries","Index")
</p>
現在我們來運行我們的項目:如果是從我的csdn上下載的,默認里面有3條數據了。
運行的時候,我們手動在地址欄的后面輸入Guestbook/Show/1,其中1是entry的id號,在controller里面我們不是留了一個參數嗎?在Asp.NET MVC中,你可以這樣傳遞參數,完整模擬路徑如下
http://localhost:端口號/Guestbook/Show/1
跳轉后,頁面默認如下:因為你還沒有登錄,所以不會顯示Edit超鏈接
數據庫中的表數據一覽,目前id只有1,2,3,所以測試的時候,不要輸入其他的
①輸入地址后,顯示效果如下
測試我們先注冊一個用戶,名字叫 茗洋芳竹,密碼叫123456
注冊好了,會自動登陸
輸入Show/2,因為id=2的信息是 name等於茗洋芳竹,是本人,所以顯示了Edit超鏈接
我猜想,如果你以前做過WebForm的話,聰明的你肯定已經領悟出來什么了.
3.2.2 ViewBag
跟 ViewDataDictionary一樣,ViewBag也是把數據傳遞給視圖使用的一種手段.ViewBag使用了C#4.0中的 的dynamic語法.
它不是使用key字符串在集合里存儲對象了,你可以在你的controller中簡單的設置一下dynamic類型的ViewBag的一個屬性.
hasPermission是ViewBag的一個根本不存在的屬性,這里名字隨便取,因為ViewBag是個dynamic類型的.不懂dynamic的可以查看一下C# dynamic資料
如果采用ViewBag的方式
那么Show頁面稍微改下就行了
bool那里面的代碼可以不要了,if后面的那個條件,直接改成
就行了.
估計ViewBag你已經會用了,Model從哪里來的,你先不用管,估計你也猜到了,我們在Controller中調用View()方法的時候,加了一個實體對象作為參數.那么這里你就可以用Model來等效於你后台傳來的實體對象那樣使用就行了.
盡管ViewData和ViewBag的都為解決數據傳遞視圖的問題而提供了很多的靈活性,但是也因此付出了很大的代價.如果你偶爾把一個dynamic屬性名稱敲寫錯了,編譯的時候是找不到錯誤的,這些技術所以也有不友好的地方.除此之外,在Visual Studio中 dynamic的屬性,編寫代碼時候是沒有提示的,ViewData也沒有,你要記得ViewData中的鍵名稱。(盡管有第三方企業工具:比如說JetBrains ReSharper可以支持它)
除此之外,你也不能很容易地在dynamic屬性上綁定元數據.而在ASP.NET MVC框架里面,你可以利用特性的優勢,直接把元數據綁定到現在比較常用的類型上(比如說,在System.ComponentModel.DataAnnotations命名空間下的驗證特性,你可以用來標記一個字段是否不能為空(required),一個字段的長度限制等等),這些特性在dynamic的ViewBag屬性上都是不能使用的
取而代之的是,你可以使用強類型視圖,一個使用了強類型類的視圖.通過這個方法,你就可以利用vs獲得智能感知和vs的的重構工具來高效快速的寫代碼了.你也可以用特性驅動元數據的方法獲得好處.在下一節我們來研究一下.
3.2.3 強類型視圖,一個視圖模型
當你使用基於Razor的視圖的時候,你的視圖可以繼承兩種類型,默認的是System.Web.Mvc.WebViewPage或者System.Web.Mvc.WebViewPage<T>,WebViewPage<T>繼承WebViewPage,所以提供了一些WebViewPage沒有的一些特征.
下面是 WebViewPage<T>內部骨架(Skeleton)的一些定義
除了提供了強類型的ViewData.Model的包裝,然后你就可以使用Model外,WebViewPage<T>還提供了兩個可以在視圖中可以使用的AjaxHelper和HtmlHelper對象.
為了使用強類型視圖,首先你要在你的Controller的action中設置ViewData.Model屬性,在Listing 3.4中,我們查出了所有的guestbook entries,然后展示在列表頁面上,在View方法中我們傳遞了一個實體.換句話說,也就是換個形式封裝設置了ViewData.Model屬性了,所以你在視圖頁面就可以直接使用Model屬性了.
我們修改GuestbookController中的Index操作和相對應的視圖頁面(Guestbook/Index.cshtml)
在Index視圖上就是用這個Action的.即使是一個弱類型的WebViewPage類,但是也可以使用ViewData.Model屬性的.但是這個屬性是一個類型對象,我們需要轉換一下結果才能有效的使用.取而代之,我們可以使用@model關鍵字來使我們的父類WebViewPage<T>指定model類型
-
@using GuestInfo.Models
-
@model List<GuestbookEntry>
通過使用@model關鍵字我們指定了model的類型,現在我們的視圖已經繼承了於WebViewPage<T>而不是WebViewPage了.現在我們已經有了一個強類型的視圖了.我們也可以使用@using關鍵字導入命名空間.在下一節里,我們將要看一下,在一個視圖里我們怎樣使用model對象來展示信息.
3.2.4 在一個視圖里面展示視圖model的數據
在一個視圖里面展示信息,通常的,你可能使用HtmlHelper對象去輔助讓這個model生成html,思考一下下面一個展示了一個完整的Guestbook entry信息的代碼,這個代碼寫在Views/Guestbook/Show.cshtml
<h2>Guestbook Entry</h2>
<dl>
<dt>姓名:</dt>
<dd>@Model.Name</dd>
<dt>日期:</dt>
<dd>@Model.DateAdded</dd>
<dt>消息:</dt>
<dd>@Model.Message</dd>
</dl>
<p>
@{
bool hasPermission = (bool)ViewData["hasPermission"];
}
@if (ViewBag.hasPermission) // ViewBag.hasPermission
{
@Html.ActionLink("Edit", "Edit", new { id = Model.Id });
}
@Html.ActionLink("返回 Entries", "Index")
</p>
上面這段代碼我相信你們應該能看懂了.看不懂的,在評價里面說一下
當我們在屏幕上展示未編碼的用戶輸入的信息的時候,我們寧可不留出存在多種腳本攻擊的可能性.還好這個數據在呈現於屏幕之前已經自動編碼了.如果你想展示一個沒有編碼過的文本,你可以使用Html.Raw方法來使那些信息以純文本的形式展現.
在login頁面里面,我們使用一個視圖model對象來表達了一個表單的全部的數據,代碼如下
這個登陸頁面也非常簡單,如下
由於在Log on屏幕里,我們選擇一個強類型視圖,我們使用了內置的助手去幫助為每一個節點生成html.為了替換掉使用弱綁定來呈現action的參數,我們可以使用基於表達式的HtmlHelper拓展來創建不同類型的input節點,代碼如下(Views/Accout/register.cshtml)
@model GuestInfo.Models.RegisterModel
@{
ViewBag.Title = "注冊";
}
<hgroup class="title">
<h1>@ViewBag.Title.</h1>
<h2>創建新帳戶。</h2>
</hgroup>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<fieldset>
<legend>注冊表單</legend>
<ol>
<li>
@Html.LabelFor(m => m.UserName)
@Html.TextBoxFor(m => m.UserName)
</li>
<li>
@Html.LabelFor(m => m.Password)
@Html.PasswordFor(m => m.Password)
</li>
<li>
@Html.LabelFor(m => m.ConfirmPassword)
@Html.PasswordFor(m => m.ConfirmPassword)
</li>
</ol>
<input type="submit" value="注冊" />
</fieldset>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
功能類似於
<label for=”UserName”>姓名</label>
<input id=”UserName” name=”UserName” type=”text” value=”” />
由於這個label和input都可以用表達式(expression)來生成,所以我們不用再記復雜的label和input名稱了
HtmlHelper被設計時就支持強類型視圖
由於我們的表單都是使用強類型視圖生成的,所以我們在controller中可以好好設計action,讓這個表單可以post提交上去.
而不是列舉每一個input字段作為一個action方法的參數,我們可以綁定所有的參數給同一個view model(我們曾經想要展現的視圖)
在這里可以有兩個參數,當然你也可以有多個.這里你也看到了,這里有個returnUrl,而不是表單中input節點.第一個參數,是一個model,封裝好了所有input中的值
隨着HtmlHelper對強類型視圖支持的越來越好,如果你只是僅僅依靠這些拓展來生成HTML,那么在你的視圖里面就會有一些重復.舉個例子,如果每個input節點都想要一個對應的label,那么為什么不能包括它呢?每一個用戶接口都是不一樣的.ASP.NET MVC團隊不能猜對每個使用的input和label的布局的人想要什么樣的布局(layout).雖然每一個input節點都應該有有個label.但是這個現存的helper方法可以創建那些不需要label的input節點.相反的,我們可以使用ASP.NET MVC2中的特征的優點--模版--去掌握一個更標准化的html的生成方式
3.2.4 使用強類型模版
如果你現在已經轉向用基於表現層的model形式的強類型視圖模式開發,那么你將要開始發現越來越多的句式出現了。如果你的表現層model對象在表單里有個boolean屬性,你肯定會去使用checkbox在表單里面呈現。Email地址,password字段等等都是的。input節點沒有對應的驗證信息是很少出現的。
除了使用HtmlHelper以外,在ASP.NET MVC2開始出現的時候,templated helpers新的特性出現了,它被設計基於強類型視圖用來輔助設計生成html的一個技術。Templated helper可以為一個完整的model生成html或者為一個member生成html。
3.3.1 EditFor和DisplayFor 模版
這兩個不同的模版集被分成了編輯(editor)和展現(display)模版。這個編輯和展現的模版有下面代碼生成
雖然在使用模版,同樣效果用字符串方式的方法對弱類型的視圖不利,但是我們可以使用基於表達式的方法來在強類型視圖里面獲得優勢(lambda表達式語法)。如果我們的model比較簡單,我們可以使用ForModel系列的方法,它會重復遍歷model中的每一個成員(
member),然后生成html。
在我們的修改密碼的頁面上布局比較簡單,我們可以使用EditorForModel方法來生成一個用於編輯信息的表單
①我們在Models/AccountModels.cs里面我們先添加一個類
這個代碼和LocalPasswordModel代碼一樣的,我們復制一下代碼改一下名字。
雖然已經有了更改密碼的頁面了,但是這里我們只是練習一下EditorForModel的用法,還希望不用嫌麻煩
接下來我們在Controller/AccountController.cs用法
添加一個Action
public ActionResult ChangePasswordPage() {
ChangePasswordModel newPassword = new ChangePasswordModel();
return View(newPassword);
}
接下來我們右鍵該action名字,添加一個視圖。
視圖代碼如下:
@{
ViewBag.Title = "ChangePasswordPage";
}
@using (Html.BeginForm())
{
<div>
<fieldset>
<legend>用戶信息</legend>
@Html.EditorForModel();
<p><input type="submit" value="改變密碼"/></p>
</fieldset>
</div>
}
登陸:
登陸成功后,我們先看一下原配的,點擊一下你的名字,進入更改密碼界面
接下來我們修改一下地址欄
但是有時,我們不可能只要這么簡單的輸出html,為了更靈活,比如說我們調整布局,或者添加更多的html標簽等等
接下來我們使用EditorFor模版
當然,你把EditorFor改成Editor也行,只不過有的名稱你可能記不住,所以說For系列的模版,例如EditorFor而不是Editor,所以正確性更高
代碼如下
3.3.2 內置模版
不出所料,ASP.NET MVC有一套自己的編輯和展示的模版,大致如下
除了Collection和Object模版,其他的模版都呈現的是唯一的值,Object模版循環訪問ModelMetadata.Properties集合中的每一項,每一項展現的時候都調用對應的display模版.Collection模版循環訪問model對象中的每一項,並為列表中的每一項調用對應的display模版顯示。
正如你預料到的,展示模版在瀏覽器中呈現為一個節點,例如純文本或者一個錨標簽,相反地,editor(編輯)模版展現的是表單中的節點,默認的編輯模版在表3.3都列出來了
3.3.3 查找模版
<Area>/<ControllerName>/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml) <Area>/Shared/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml)
如果模版不在這些文件夾里,或者視圖不在域里,這個默認的視圖查詢地址就會被使用
<ControllerName>/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml) Shared/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml)
舉個例子:
我們現在要在更改密碼頁面上展現一個自定義的ChangePasswordModel模版。model我們已經有了,現在我們只需要定義一個更model類型名字(ChangePasswordModel)一樣的模版就行了。文件放的路徑如下圖
左邊一個,只給AccountController使用,右邊一個,所有的控制器都可以使用,EditorTemplates文件夾是自己建立的
3.3.4 自定義模版(難)
總而言之,有兩種理由去創建一個自定義模版
■ 創建一個自定義模版 ■ 重寫現有的模版
首先我們看一下在控制器明確的視圖文件夾下的模版解決方案規則,因此我們能夠很明確的在Shared文件夾下重寫一個內置的模版,然后我們在重寫控制器明確的視圖文件夾里。
解釋一下“控制器明確的視圖文件夾”:例如GuestController這個就是控制器明確了,名字是Guest,所以我們能找到對應的視圖文件夾,例如 Views/Guest/… 這個最終的文件夾路徑就是 控制器明確的視圖文件夾
打個比方,你可能有一個應用廣泛的模板,用於顯示的電子郵件地址.然后在一個域或者控制器模版的文件里提供一個模版。
在大多數情況下,模版跟創建一個類型是一樣的。ChangePasswordModel模版標簽如下
創建一個新的Object.cshtml.里面用了EditorFor模版,每一個被P標簽包裹。局部模版有什么好處?
首先,局部模版在視圖里面都是通過名稱找到的。避開在視圖中明確指定哪一個模版被調用的需要,模版可以從model元數據信息中找到。此外模版能夠在ViewDataDirectory中獲得額外的信息,然而局部模版和其他的頁面是獲得不到的。這些信息在View.Data.ModelMetadata屬性中.只有在ASP.NET MVC中模版才有ModelMetadata屬性.在局部模版和視圖,這些屬性都為null
使用ModelMetadata屬性時候,你能夠獲得從model元數據提供器生成的所有元數據信息。這些包括關於model的model類型信息,屬性,和元數據。
Model類型信息包括的屬性都在表3.4列出來了
除了一些model類型信息之外,ModelMetadata也包含了其他的metadata,默認的都是來自特性.如圖表3.5
在我們自定義模版中,我們研究一下這些model元數據,然后去自定義HTML去呈現。除了在表3.4和3.5列出來的屬性之外,ModelMetadata對象暴露了一個IDictory<string,object>類型的AdditionValues屬性。這個屬性包含了一些來自自定義model元數據提供者的額外的元數據信息.舉個例子:如果你想展示一個必填的(required)字段,我們只需要在我們的自定義模版中檢測這個IsRequired屬性。比如說我們要裝飾一下我們的實體中的一個DataType.DateTime數據類型的特性,我們可以用一個日期捕獲插件來自定義個模版來呈現時間。
實踐一下,我們可能要重寫一下現有的模版,因為這個現有的Object模版可能適合,可能不適合我們的需求。這個model的元數據不能包括任何樣式信息,所以自定義的樣式和其他的標簽都是通過重寫內置的模版完成的。但是很多網站都趨向於標准的通用的用戶接口布局,比如說我們通常把一個label放在一個input上面用作標記和提醒用戶,或者用一個*來標記這個input是必須輸入內容的。我們只需要重寫模版,就可以潛移默化地影響整個站點。
比如說,我們可能希望把label放在跟input放在同一行,而不是在一列后右對齊,為了達到這個目的,我們需要重寫現有的Object模版
①我們首先在 Views/Shared/下面建立一個EditorTemplates文件夾,添加一個Object.cshtml,代碼如下
@foreach (var prop in ViewData.ModelMetadata.Properties
.Where(pm => pm.ShowForEdit
&& !ViewData.TemplateInfo.Visited(pm)))
{
<div class="editor-field-container" style="clear:both">
@if (!String.IsNullOrEmpty(
Html.Label(prop.PropertyName).ToHtmlString()))
{
<div class="editor-label float-left">
@Html.Label(prop.PropertyName)
</div>
}
<div class="editor-field float-left">
@Html.Editor(prop.PropertyName)
@Html.ValidationMessage(prop.PropertyName, "*")
</div>
<div class="cleaner" style="clear:both"></div>
</div>
}
②接下來修改Views/Account/Login.cshtml代碼
@model GuestInfo.Models.LoginModel
@{
ViewBag.Title = "登錄";
}
<hgroup class="title">
<h1>@ViewBag.Title.</h1>
</hgroup>
<section id="loginForm">
<h2>使用本地帳戶登錄。</h2>
@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>“登錄”表單</legend>
@Html.EditorForModel()
<input type="submit" value="登錄" />
</fieldset>
<p>
@Html.ActionLink("Register", "Register") (如果你沒有帳戶)。
</p>
}
</section>
<section class="social" id="socialLoginForm">
<h2>使用其他服務登錄。</h2>
@Html.Action("ExternalLoginsList", new { ReturnUrl = ViewBag.ReturnUrl })
</section>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
按F5運行效果,登陸頁面如下:
我們創建了一個foreach循環,一層一層地遍歷了在編輯時以前應該顯示的或者不應該顯示的ModelMetadata.Properties屬性.展示一個label,editor模版,還有驗證信息,把每一個屬性放在一個div標簽里面.最后我們包括了一個cleaner div重置了浮動樣式應用於實現列布局.這個最終效果在圖3.5
在一個全局的模版中通過放一個普通的呈現邏輯,我們可以很容易的跨站點為我們的視圖,提供標准化display和editor布局.為了達需要自定義化的效果的域,我們要有選擇性的重寫或者提供一個新模版,通過在一個地方標准化和封裝我們的呈現內容的邏輯,我們在一個地方編寫了很少的代碼就影響了整個站點(site),如果我們想要改變我們的時間插件,我們可以簡單的寫一個data-time模版,就可以很容易改變我們的站點,讓它呈現不同的內容。
3.4 總結
MVC框架可以在視圖(頁面)里減少很多商業邏輯,不幸運的是,視圖給我們帶來了很多必須掌握的復雜的東西,為了應付這個復雜度和難點,為了提高視圖和其他模塊的結合性,我們研究了怎樣使用強類型視圖和隔離開的視圖model,隨着分離的視圖model的普遍增加,使用模版從這些視圖model中獲得元數據來呈現內容的概念已經成為可能。在分隔開的視圖model中,在你的應用程序中,我們還是要保持視圖和model是分離開的理念。
現在我們理解了視圖是怎么工作的了,下一章我們將探討一下控制器基礎
第二章代碼下載:http://download.csdn.net/download/yangyanghaoran/5207734
額外贈送:
臨時去除迅雷看看廣告的做法【原創】
①打開資源管理器
②打開迅雷看看,播放任意電影,緊接着會有廣告
③查看資源管理器,多了一個這個進程 XLUEOPS.exe,我們只要在廣告播放的30秒內手動 關閉此進程,就可以立即 去掉廣告,每次放廣告,迅雷看看都會加載此進程
④右鍵單擊它,結束進程,就可以臨時去掉廣告
其他方法:
如果你裝了360安全衛士,直接點一鍵加速,就可以臨時去掉廣告
個人覺得3.3.4 自定義模版有點難,看不懂的也不用糾結我。這里只是視圖基礎,具體的以后再講
關於ASP.NET MVC4 IN ACTION系列目錄地址已經生成:點擊查看目錄