開發人員之因此花費大量時間來重點設計控制器和模型對象,是由於在這些領域中,精心編寫的整潔代碼是開發一個可維護Web應用程序的基礎。html
視圖的職責是向用戶提供用戶界面。當控制器針對被請求的URL執行完合適的邏輯後,就將要顯示的內容委託給視圖。web
不像基於文件的Web框架,好比ASP.NET Web Forms和PHP,視圖自己不會被直接訪 問,瀏覽器不能直接指向一個視圖並渲染它。相反,視圖老是被控制器渲染,由於控制器爲它提供了要渲染的數據。瀏覽器
在一些簡單的狀況中,視圖不須要或須要不多控制器提供的信息。更常見的狀況則是控制器須要向視圖提供一些信息,因此它會傳遞一個數據轉移對象,叫作模型。視圖將這個模型轉換爲一個適合顯示給用戶的格式。在ASP.NET MVC中,完成這一過程由兩部分操做,其中一個是檢查由控制器提交的模型對象,另外一個是將其內容轉換爲HTML格式。安全
在最簡單的狀況中,向控制器發出一個請求,控制器返回一個視圖,其實就是一些靜態的HTML。很容易,可是動態性很差。前面說過,視圖提供了一個模板引擎。下面咱們就利用這個模板引擎,從控制器向視圖傳遞少許數據。最簡單的方法就是使用ViewBag。ViewBag具備侷限性,可是若是隻是向視圖傳遞少數數據,他仍是頗有用的。服務器
這與前面的Index方法幾乎相同,可是注意控制器將ViewBag.Message屬性值設置成一個字符串。而後再調用return View()。框架
這一節要介紹ASP.NET MVC如何找到正確的視圖進行渲染,以及如何重寫這個視圖,爲一個控制器操做指定特定的視圖。佈局
本章到如今爲止介紹的控制器操做簡單地調用return View()來渲染視圖,還不須要指定指定視圖的文件名。能夠這麼作,是由於它們利用了ASP.NET MVC框架的一些隱式約定,這些約定定義了視圖選擇邏輯。 網站
當建立新的項目模板時,將會注意到,項目以一種很是具體的方式包含了一個結構化的View目錄。編碼
在每一個控制器的View文件夾中,每一個操做方法都有一個同名的視圖文件與其對應。這就提供了視圖與操做方法關聯的基礎。spa
與ASP.NET MVC中的大部分約定設置同樣,這一約定是能夠重寫的。若是想要Index操做方法渲染一個不一樣的視圖,能夠向其提供一個不一樣的視圖名稱。例如:
或
經過ViewBag向視圖傳遞少許數據,儘管對於簡單的狀況,使用ViewBag很容易,可是處理實際數據時,ViewBag就變得不方便,這時就須要使用強類型視圖。
咱們首先看一個不合適使用ViewBag的例子。沒必要擔憂要鍵入這些代碼,它們只是用來進行說明的。
強類型視圖容許設置視圖的模型類型。所以,咱們能夠從控制器向視圖傳遞一個在兩端都是強類型的模型對象,從而得到智能感知、編譯器檢查等好處。
對於在視圖中常用的名稱空間,一個較好的方法就是在Views目錄下的web.config文件聲明。
從技術角度講,數據從控制器傳送到視圖是經過一個名爲ViewData的ViewDataDictionary(這是一個特殊的字典類)。咱們可使用標準的字典語法設置或讀取其中的值,實例以下:
ViewData["CurrentTime"]=DateTime.Now;
ViewBag是ViewData的動態封裝器。這樣咱們就能夠按照下面的方式來設置值:ViewBag.CurrentTime=DateTime.Now;
所以,ViewBag.CurrentTime等同於ViewData["CurrentTime"]。
通常來講,咱們將遇到的大部分代碼使用ViewBag,而不是ViewData。 大多數狀況下,這兩種語法彼此之間並不存在真正的技術差別。ViewBag相對於字典語法而言僅僅是一種受開發人員歡迎、看上去很好看的語法而已。
ViewData和ViewBag
兩者很明顯的一個差別就是隻有當要訪問的關鍵字是一個有效的C#標識符時,ViewBag才起做用。例如,若是在ViewData["Key With Spaces"]中存放一個值,那麼就不能使用ViewBag訪問。由於這樣根本就沒法經過編譯。
另外一個須要知道的重要差別就是,動態值不能做爲一個參數傳遞給擴展方法。由於C#編譯器爲了選擇正確的擴展方法,在編譯時必須知道每個參數的正確類型。
若是其中任何一個參數是動態的,那麼就不會經過編譯。例如這行代碼就會編譯失敗:
@Html.TextBox("name",ViewBag.Name).要使這行代碼經過編譯有兩種方法:第一是使用ViewData["Name"]。第二種是把ViewData["Name"]值轉換成一個具體的類型(string)ViewData["Name"]。
如剛纔所述,ViewDataDictionary是一個特殊的字典類,而並不僅是一個通用的Dictionary。緣由之一在於,它有一個額外的Model屬性,容許向視圖提供一個具體的模型對象。由於ViewData中只能有一個模型對象,因此使用ViewDataDictionary向視圖傳遞具體的類十分方便。這樣一來,視圖就能夠指定他但願哪一個類做爲模型對象,從而讓咱們可以利用強類型。
視圖一般須要顯示各類沒有直接映射到域模型的數據。
把與視圖主模型無關的數據存放在ViewBag屬性中,能夠很容易地實現這些數據在視圖中的顯示。當具備一個清晰定義的模型和一些額外的引用數據時,這種方法尤其有用。這種技術的一種常見的應用是使用ViewBag爲下拉列表提供表單選項。例如,MVC Music Store項目的Album Edit視圖須要填充Genres和Albums下拉列表,可是這些列表不適合放到Albums模型中。爲了應對這些狀況,同時不適用無關信息影響Album模型,咱們能夠將Genre和Album的信息保存到ViewBag中。以下所示:
這麼作固然可以完成要求,而且也爲在視圖中顯示數據提供了一種靈活的方法。可是這並非一種應該常用的方法。通常應該堅持使用強類型模型對象————必須使全部數據都是強類型數據,以便視圖編寫人員可以利用智能感知功能。
如何建立視圖呢?能夠手動建立視圖文件,而後把它添加在Views目錄下。
顯示添加視圖對話框最簡單的方法就是在操做方法上右擊。
Razor視圖引擎是ASP.NET MVC3中新擴展的內容,而且也是它的默認視圖引擎。
Razor經過理解標記的結構來實現代碼和標記之間儘量順暢的轉換。
不要過多地考慮
Razor的設計理念是簡單直觀。對於大多數應用,咱們沒必要關心Razor語法----只須要在插入代碼時,輸入HTML和@符號。
Razor中的核心轉換字符是「@」字符。這個單一字符用做標記-代碼的轉換字符,有時也反過來用做代碼-標記的轉換字符。
Razor表達式是用HTML自動編碼的。
理解HTML和JavaScript編碼的安全隱患是很重要的。不正確的編碼會使網站和用戶處在危險境地。
Razor在視圖中除了支持代碼表達式之外,還支持代碼塊。
代碼塊除了須要@符號分割以外還須要使用花括號。
<span>@model.Message</span>
Razor中的隱式代碼表達式老是採用HTML編碼方式。
代碼表達式的值被計算並寫入到響應中,這就是在視圖中顯示值的通常原理。
1 <span>1+2=@(1+2)</span>
有些狀況下,須要顯示地渲染一些不該該採用HTML編碼的值,這是能夠採用Html.Raw方法來保證該值不被編碼。
<span>@Html.Raw(model.Message)</span>
不像代碼表達式先求得表達式的值,而後再輸出到響應,代碼塊是簡單地執行代碼部分。
1 @{ 2 int x=123; 3 string y="because."; 4 }
這個例子顯示了Razor中混用文本和標記的概念:
1 @foreach(var item in items) 2 { 3 <span>Item @item.Name</span> 4 }
Razor查找的標籤的開始位置以肯定什麼時候將代碼轉換爲標記。然而,有時可能想在一個代碼塊以後當即輸出純文本。例如,在下面的這個例子中就是展現如何在一個條件語句塊中顯示純文本。
1 @if(showMessage){ 2 <text>This is plain text.</text> 3 }
或
1 @if(showMessage){ 2 @:This is plain text. 3 }
用"@@"來編碼"@"以達到顯示"@"的目的。
@**@
調用泛型方法的代碼包括尖括號。
@(Html.SomeMethod<AType>())
Razor的佈局有助於使應用程序中的多個視圖保持一致的外觀。
每個視圖都是使用Layout屬性來指定它的佈局。若是多個視圖使用同一個佈局,就會產生冗餘,而且很難維護。
_ViewStart.cshtml頁面可用來消除這種冗餘。這個文件中的代碼鹹魚同目錄下任何視圖代碼的執行。這個文件也能夠遞歸的應用到子目錄下的任何視圖。
當建立一個默認的ASP.NET MVC項目時,你將會注意到在Views目錄下會自動添加一個_ViewStart.cshtml文件,它指定了一個默認佈局。
1 @{ 2 Layout="~/Views/Shared/_Layout.cshtml"; 3 }
由於這個代碼優先於任何視圖運行,因此一個視圖能夠重寫Layout屬性的默認值,從而從新選擇一個不一樣的佈局。若是一組視圖擁有共同的設置,那麼_ViewStart.cshtml文件就有了用武之地,由於咱們能夠在它裏面對共同的視圖配置進行統一設置。若是有視圖須要覆蓋統一的設置,咱們只須要修改對應的屬性值便可。