[注:此文對應Chapter 3:Views]
一、View的功能:
1.View用來呈現頁面UI,通過Controller來指定View:
要注意的是,MVC和以前基於文件的Web應用不同,URL指向的並不是最終顯示UI的文件,
在MVC中,和URL打交道的是Controller,而不是View,是通過Controller中的Action Method來指定要顯示的View
2.Controller中指定View的規則:
在Controller中返回值類型為ActionResult的Action Method可以指定一個用來顯示UI的View,
返回視圖的代碼:return View([參數]);
返回View的View方法有三種不同參數,對應不同需求:
1)參數為空:return View()
這種為最常用的格式,用來返回和Action方法名同名的默認視圖;
2)參數為視圖文件名:return View("HelloWorld.cshtml")
使用這種格式,可以將Action方法Url指向View/ControllName/HelloWorld.cshtml
即,可以將Action方法Url指向View/ControllName下,和Action不同名的View文件
3)參數為任意位置視圖文件:return View("視圖相對路徑")
在這種格式下,可以將Action方法對應的Url指向任意視圖文件
Controller代碼:
1 public class HomeController : Controller 2 { 3 public ActionResult Sample() 4 { 5 ViewBag.Message = "Hello World, this is a Sample!"; 6 return View("~/Views/Shared/Error.cshtml"); 7 } 8 }
上面的代碼中,HomeController的Action方法Sample(), 將Url: 域名/home/sample 指向了項目自動生成的Error視圖
運行程序得到的效果(注意地址):

二、ViewData和ViewBag
1.ViewData
原則上,controller中的數據是通過ViewDataDictionary(字典類)類的對象ViewData來傳遞給View
如:ViewData["CurrentTime"] = DataTime.Now;
2.ViewBag
從MVC3開始,將上面的語法進行簡化,使用ViewBag動態包裝ViewData,允許我們使用下面的語法:
ViewBag.CurrentTime = DataTime.Now
這種寫法和上面的字典模式完全相同。
注意:
1)如果ViewBag.關鍵詞其中的關鍵字中有空格,則不能編譯通過;
2)ViewBag不能直接作為動態參數進行傳值
如: @Html.TextBox("name",ViewBag.Name)——錯誤!
@Html.TextBox("name",ViewData["Nmae"]) —— 正確!
@Html.TextBox("name",(string)ViewBag.Name)——正確!
三、基於強類型的View(Strongly Typed Views)
1.原理:
ViewData是ViewDataDictionary對象,該類不同於普通Dictionary類,其中包含了一個Model property,允許
從Controller中,將一個(只能是一個)指定對象傳到View中。
這種方式不同於使用ViewBag,是強類型。不需要再進行類型指定,直接就可以使用該對象的屬性和方法。
2.使用:
1)將要傳到View中的對象作為參數給View()方法:
如:return View(albums);
2)在View中,用model接收該對象,直接包含新型信息,不需要再進行類型指定。
@model IEnumerable<Album>
<ul>
@foreach(Album a in Model)
{ <li>@a.Title</li>}
</ul>
3.在View中添加命名空間引用
1)直接在.cshtml文件中添加
@using MvcMusicStore.Models
2)在Views文件夾的web.config文件中添加,對整個Views文件夾中所有View都有效
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
。。。。
<add namespace="MvcMusicStore.Models" />
</namespaces>
</pages>
4.通過NuGet獲取書籍配套例程代碼:
建好一個MVC4項目,【工具】——【庫程序包管理器】——【程序包管理控制台】
在命令行中鍵入:Install-Package Wrox.ProMvc4.Views.AlbumList

這將添加兩個文件夾到項目中,Album類和AlbumController在\Samples\AlbumList中,視圖文件Albums.cshtml在\View\Albums中
對應的URL為:域名/albums/listweaklytyped和域名/albums/liststronglytyped
分別非強類型和強類型方式訪問,可以通過代碼比較其區別
四、View Models
1.起因——Conroller默認只能傳遞一個強類型對象到View中:
1)ViewData所繼承的ViewDataDictrionary類中,只能包含一個Model類,所以,每次只能從Controlller傳到View一個對象。
2)View中,大多數情況下需要多個后台傳過來的對象來進行綁定顯示或操作,單個后台穿過來的類對象不夠用,而使用ViewBag
的話,又失去了強類型的好處。
2.解決方案:View Modles
寫自定義的View modle class,將你需要的所有信息都包含其中。
如:自定義一個購物車Modle類
1 public class ShoppingCartViewModle 2 { 3 public IEnumerable<Product> Products {get;set;} 4 public decimal CartTotal {get; set;} 5 public string Message {get;set;} 6 }
這樣,就可以把你需要的所有相關購物車的所有信息綜合在一起傳遞給View,並且使用的強類型View方式
@model ShoppingCartViewModel
接收到的就是從Controller傳過來的完整信息。
3. 例子:
建好一個MVC4項目,【工具】——【庫程序包管理器】——【程序包管理控制台】
在命令行中鍵入:Install-Package Wrox.ProMvc4.Views.ViewModel
執行成功后,同上面的例子,會在項目中增加兩個文件夾:
/Samples/ShoppingCartViewModel 包含Product類、ShoppingCartViewModel類和控制器ShoppingCartController類
/Views/ShoppingCart/ 包含對應的視圖Index.cshtml

運行后的效果(域名/ShoppingCart)

五、Razor View Engine
簡單的介紹跳過去,直接寫核心的
1. 代碼表達方式
最重要的標示符在Razor中就是“@”
1)代碼表達式
如 :@對象名.屬性 ,等同於Web Form視圖中的<%: 對象名.屬性 %>
*注:
雖然Razor比較智能,能夠判斷大多數情況,自動判定到底是想要轉換后台代碼,還是直接顯示,
但也會遇到混淆的時候,可以通過下面幾種方式來避免:
A) @(后台代碼)
通過給后台代碼加(),來強制將@要轉換的內容,和其后面要直接顯示的文本分開。
B) @@將顯示為@文本
2)HTML編碼(Html Encoding)
為防止注入攻擊,Razor表達式會自動進行HTML編碼
@{string message = "<script>alert('haacked!');</script>";}
<span>@message</span>
上面的HMTL View代碼在運行時會被解釋為:
<span><script>alert('haacked!');</script></span>
這種HTML編碼是自動進行的。
在某些情況下,需要取消HTML編碼,可以使用HtmlHelp,使用HtmlStirng對象或者Html.Raw()
如:
@{string message = "<strong>This is bold!</strong>";}
<span>@Html.Raw(message)</span>
這次,就不會再被轉碼,會直接顯示為:
<span><strong>This is bold!</strong></span>
另外,使用@Ajax.JavaScriptStringEncode來編碼和Javascript相關的用戶輸入,來防止注入攻擊,如:
<script type="text/javascript">
$(function () {
var message = 'Hello @Ajax.JavaScriptStringEncode(ViewBag.Username)';
$("#message").html(message).show('slow');
});
</script>
3)代碼段:
@{代碼段}
2. Razor 語法:
1)隱式代碼表達式:
<span>@model.Message</span>
又Razor自動判斷后面的.Message是text文本還是model的property
2)顯示代碼表達式:
<span>@(model).Message</span>
在括號中的是后台代碼,其外的是文本
3)不經Html轉碼的表達式:
<span>@Html.Raw(model.Message)</span>
前面提過,Razor為防止注入攻擊,自動對用戶輸入進行HTML轉碼,如果特殊情況下不用轉碼,需要寫成上面的格式
4)代碼段:
@{
int x = 123;
string y = "hello!";
}
5)混合文本和標簽
@foreach(var item in items)
{
<span> Item @item.Name.</span>
}
6)混合代碼和文本
@if(showMessage)
{
<text>This is plain text </text>
}
或
@if(showMessage)
{
@:This is plain text.
}
注意,后面的語法@:只能針對一行代碼
7)顯示文本的@
@ 或者 @@
8)服務器端注釋:
@*
This is a multiline server side comment.
@if (showMessage) {
<h1>@ViewBag.Message</h1>
}
All of this is commented out.
*@
9)調用泛型函數(Generic Method)
@(Html.SomeMethod<AType>())
其實和顯式的Razor代碼表達式一樣,注意外面加()!
3. Layouts 布局
類似於Asp.net中的MasterPage(母板頁),用來設定統一外觀的。
設定整體布局使用的是~/_ViewStart.cshtml,它會在所有View被加載之前加載,指定母版布局視圖
@{ Layout = "~/Views/Shared/_Layout.cshtml"; }
每個View下Controller對應的文件夾中,可以添加自己的_ViewStart.cshtml,用來指定獨自使用的布局視圖,采取就近原則(替View代根目錄中的);
而且,Layout框架的賦值語句:Layout="。。。",也可以加到任意一個View文件中,作為此文件的單獨布局框架。
1)@RenderBody()
Layout Template View中的@RenderBody()用於占位。
2)@RenderSection()
一個Layout可以包含多個分塊(setions),例如,可以為Layout添加Footer分塊
<footer>@RenderSection("Footer")</footer>
在使用這個Layout的View中,需要加入@section Footer{..}代碼,來設置自己的footer,如:
@section Footer{ @@Copyright 2001-2015, All Right Received. }
但是,大多數時候,希望section都是可選的,可將其改為:
<footer>@RenderSection("Footer", required: flase) </footer>
更為通用的方式,是在設置可更改的Section時,配備一個默認的Section外觀:
<footer>
@if (IsSctionDefined("Footer"))
{
RenderSection("Footer");
}
else
{
<span>This is the default footer. </span>
}
</footer>
六、Patial View
部分View是不包含layout的局部View。
通常用來作為配合Ajax進行局部刷新。
例子:
Install-Package Wrox.ProMvc4.Views.SpecifyingViews
