接着上一篇Views的筆記
在視圖裡導入命名空間(Importing Namespaces into a View)
Razor視圖通過一套常用的命名空間編譯,這為我們省去了在使用常用類時指定必要的命名空間的麻煩。如果需要使用我們自己定義的類就必須引入命名空間或者是使用類的完整名稱(包含了命名空間),如下所示:

View Code
上面的例子使用了MyUtility類,裡面有一個GetUsefulData方法。MyUtility.cs如下所示:

上面是使用的完整類名,也可以使用@using引入命名空間,如下所示:

當視圖被編譯時,我們指定的命名空間會通過using語句導入,這樣我們就可以在視圖裡面直接引用類名。
在Web.config裡面添加命名空間
上面在視圖裡導入命名空間後,我們也隻能在目前的視圖裡面使用該命名空間下的類,如果我們想隻寫一次導入命名空間的using語句并能夠在目前項目裡所有的視圖裡面使用,可以采取在Web.config裡添加的方式,如下所示:

注意這裡的Web.config是在Views檔案夾裡面的,不是根目錄下的Web.config。
了解Razor HTML字元串編碼
XSS(跨站點腳本)是攻擊網站的一種方式,Razor會幫助我們将來自@标簽的輸出進行編碼,進而防止XSS攻擊。這也意味着在HTML裡面具有特殊意義的符号會被等同的編碼替換。例如"<"會被替換為lt;為了舉例說明,現在将MyUtility進行修改:

上面隻是一個簡單的例子,真正的攻擊非常巧妙而且不會改變頁面。可以運作程式顯示如下:
預設情況是會對輸出進行編碼,如果我們不想編碼輸出,可以傳回一個MvcHtmlString的執行個體,如下:

運作程式可以看到效果。
使用動态類型視圖(Using Dynamically Typed Views)
當建立一個強類型的視圖時,建立的類是從System.Web.Mvc.WebViewPage<T>派生的,T就是視圖模型類的類型。例如:
如果我們沒有指定具體的類型,那就建立了一個動态類型的視圖,也就是T是dynamic類型的。我們仍然能夠傳遞視圖模型對象給View,但卻是被當作動态類型的,這意味着處理該視圖模型對象類似處理ViewBag了,在動态類型視圖裡面,同樣能夠調用視圖模型對象的任何成員,隻不過要到運作時才會被檢查。使用動态類型的好處是可以傳遞不同的視圖模型類型(View Model Types)到視圖。缺點是如果我們傳遞一個不屬于該對象的成員時,當調用該視圖就會會抛異常,但在編譯的時候是發現不了這個錯誤的。這裡不推薦随便使用動态類型。
使用HTML輔助方法(Using HTML Helpers)
MVC架構裡面提供了一序列的HTML輔助方法來幫助我們生成HTML标簽,進而提高我們的開發效率。
建立内嵌的HTML輔助方法
這是最直接的使用方式,如下:

内嵌的helpers有方法名和參數,這類似于通常的C#方法。在上面的例子中,我們定義了一個CreateList的helper。
建立一個擴充的helper方法(Creating an External Helper Method)
内嵌helper方法非常友善,但是隻能在目前的視圖裡面使用,如果想在其他的視圖裡面也使用的話,可以建立一個擴充的HTML helper方法,如下:

第一個參數是擴充的HTML helper方法,是HtmlHelper對象。
在一個Helper方法裡面建立HTML标簽的最簡單的方式就是使用TagBuilder類,它讓我們不需要處理特别的字元就能夠很友善的建立HTML。
TagBuilder類是System.Web.WebPages程式集的一部分,但是使用了CLR的一個功能: type forwarding(暫且稱為類型轉遞吧,如果你有更好的解釋,記得留言給我,謝謝),這個功能讓我們能夠将程式集的某一個類型指向其他的程式集,而不用重新編譯就可以在其他的程式集裡面使用原來程式集的類型。是以這裡也是作為System.Web.Mvc程式集的一部分,因為TagBuilder從System.Web.WebPages通過類型轉遞指向了System.Web.Mvc,這也是為什麼這裡隻需要引用System.Web.Mvc這個命名空間就行了。
下面是關于TagBuilder類的一些屬性:
InnerHtml:設定HTML元素的内容,是不會被編碼的。
SetInnerText(string):設定HTML元素的文本内容,這裡的string是被編碼過的。
AddCssClass(string):添加css樣式
MergeAttribute(string,string,bool):添加特性,第一個參數是屬性的名字,第二個是值,bool類型表示是否替換已經存在的同名屬性。
HTML Helper方法的結果是一個MvcHtmlString對象,該對象包含的内容直接寫到了對用戶端的響應流裡面,記住:MvcHtmlString的内容是沒有經過編碼就直接傳遞給了Response,這也就意味着我們必須自己編碼可能導緻XSS攻擊的資料。這裡可以采取TagBuilder.SetInnerText方法,它會對字元串進行編碼,或者是顯示使用HtmlHelper對象的Encode方法進行編碼。
接着在HomeController裡面添加一個action方法,并添加對應的視圖,如下:

使用内置的HTML Helper方法(Using the Built-in HTML Helpers)
MVC架構包含了一些經過挑選的HTML helper方法,這些方法可以幫助建立HTML片段或執行通常的任務。
建立表單
兩個非常有用的方法就是 Html.BeginForm和Html.EndForm,它們幫助建立表單标簽并生成一個基于路由機制的action的屬性。如:@{Html.BeginForm("Index","Home");} @{Html.EndForm();},這些helper方法需要在Razor代碼塊裡面被調用,這會使得代碼看起不雅。一個更加優雅的方式是使用using語句,如:@using (Html.BeginForm("Index", "Home")) {...}
這種方式非常巧妙,因為BeginForm方法建立了一個MvcForm類的執行個體,這個類實作了IDisposable接口。這意味着當程式跳出using語句塊時,.NET架構會對MvcForm對象調用Dispose方法,并輸出closing Form标簽。BeginForm有很多重載的版本,不同的表單允許我們指定怎樣建立HTML表單元素的action屬性。
建立表單與回發到同一URL:BeginForm預設的重載版本是不帶參數的并生成一個指向目前action的URL,也就是這個action來處理目前的回發請求。這是MVC程式裡面常見的模式,Get和Post請求使用同一個URL來處理。Get請求展示HTML表單,Post請求驗證并處理送出過來的資料。如下:

使用Input Helpers(Using Input Helpers)
當HTML表單裡添加了Input元素後,表單才有意義。下面是一些基本的HTML Helpers用來建立Input元素,如下:

注:checkbox方法呈現了兩個input元素,一個是checkbox,一個是hidden元素,它們的name相同。有兩個input元素的原因是浏覽器不會送出沒有被選中的checkbox的值。使用一個hidden控件確定在這種請求發生時MVC架構也能夠擷取hidden的值。
如果我們想指定一個值,可以使用标準的Razor句法,像這樣:@Html.CheckBox("myCheckBox", Model),一個更加有趣的重載版本是隻擷取一個參數,這個參數被用來搜尋視圖資料,ViewBag以及視圖模型。舉個例子:如果調用@Html.TextBox("DataValue"),MVC架構視圖尋找跟該鍵值DataValue一緻的資料項,搜尋的路徑如下:
• ViewBag.DataValue • ViewData["DataValue"] • @Model.DataValue
第一個被搜到的值被用來設定建立的HTML元素的value屬性值,如果我們指定一個像DataValue.First.Name,那搜尋會變得更加複雜,會檢查如下的值是否移植:

如上所示,有很的排列的,一旦第一個值找到,搜尋就會終止。這裡我們或許會擔心程式的性能,記住一點通常情況下,隻有非常少的項在ViewBag或ViewData裡面,是以搜尋并不會花費很長時間。input helper方法會自動編碼資料防止XSS。
使用強類型的Input Helper方法(Using Strongly Typed Input Helpers)
針對上面每一個基本input方法都有一個對應的強類型的Helper方法。如下所示:

這裡會用到Lambda表達式,傳遞給表達式的值是視圖模型對象,并且能夠查詢到用來設定value值的字段或屬性。
添加Attributes到HTML:大多數helper方法具有一個讓我們可以添加任意的屬性到以建立的HTML元素,我們可以使用動态類型來表述屬性及其關聯的值,像這樣:
@Html.TextBox("MyTextBox", "MyValue",new { @class = "my-ccs-class", mycustomattribute = "my-value" })
建立Select元素(Creating Select Elements)
下面展示了可以用來建立Select元素的HTML helper方法:

Select helper方法擷取SelectList或MultiSelectList參數,這兩個參數不同的是MultiSelectList具有讓我們能夠指定一個或多個被選中項的構造器。這兩個類都是操作對象的枚舉序列。假設有這樣一個類Region:public class Region{public int RegionID{get;set;} public string RegionName{get;set;}},action方法在視圖放置了一個SelectList對象,如下:

正如我們所看到的,RegionID和RegionName的屬性值使用在select元素包含的option的inner文本和value值。
建立連結和URL(Creating Links and URL)
這裡介紹的HTML helper方法讓我們使用路由系統的輸出URL生成功能(前面的章節有介紹)呈現HTML連結和原始的URL。這些helper方法的輸出依賴于我們程式的路由配置。
下面是一些有關的方法展示:

使用WebGrid Helper(Using the WebGrid Helper)
該方法生成以網格形式展示資料項的HTML元素,使用了HTML table元素。下面通過示例說明:
在HomeController裡面添加一個action Grid如下:

對應的視圖代碼如下:

我們在兩個部分使用WebGrid helper方法,第一個部分包含在Razor代碼塊裡面并且定義WebGrid對象。設定source參數值為視圖模型(Product對象),這些是展示在grid裡的項。我們将定義和使用grid分為兩個步驟,定義裡面另一個參數提供了rowPerPage,WebGrid支援分頁。
有非常多的構造器參數來讓我們指定grid的生成行為,下面是一些參數的描述:
Source:資料源(預設為null) columnNames:定義被用作列資料源的項(預設為null) rowsPerPage:指定每頁多少行(預設為10) canPage:啟用/禁用分頁(預設true)
canSort:啟用/禁用排序(預設true)
第二個部分使用WebGrid helper方法生成HTML,這裡是通過調用GetHtml方法實作。傳遞給這個方法參數讓我們可以控制HTML的呈現。
WebGrid.GetHtml方法的參數清單如下:
列的參數給我們提供一種配置個性化列的方式。運作下程式可以試試效果,很明顯能夠知道每點選一次header列,會重新加載所有資料,如果需要考慮性能這裡可以使用緩存。
如果我們不喜歡在視圖裡面定義WebGrid helper方法,感覺這應該是在action方法裡面完成的,感覺沒錯,我們可以在action裡面定義,如:

使用圖表helper方法(Using the Chart Helper)
MVC裡面的Chart Helper提供非常多的功能來展示圖表,這裡僅僅是簡要介紹,詳詢MSDN的相關内容。添加一個action方法,如下:

裡面一個非常重要的方法是Chart.Write,它會将生成的圖表作為圖檔直接響應輸出。,最簡單的在web頁面裡面包含圖表的方式就是使用部分視圖。
還有一些其他的内置Helper方法如下:
Crypto(提供常用的加密散列功能) WebMail(通過SMTP發郵件) Json(處理Json資料) ServerInfo(擷取關于伺服器的資訊) WebImage(加載及簡單的處理圖檔)
使用片段(Using Sections)
Razor引擎支援的分片的概念,讓我們能夠在一個布局裡面提供内容區域。Razor分片功能能夠更好的控制在視圖的那部分插入布局以及在放置在哪個位置。如下:

@RenderSection("Footer",false)這個重載版本表示Footer Section是可選的,當我們定義了Footer Section時則顯示出來,如果沒有定義也不會抛異常。
使用部分視圖和強類型的部分視圖
通過示例下說明:

注:Razor視圖引擎用同樣的方式尋找部分視圖,這意味着我們可以指定了控制器的部分視圖并且可以重載在Shared檔案夾下的同名部分視圖,這可能有點怪,但是一種最常用的部分視圖使用方式就是在layout裡面呈現内容。
使用子Action(Using Child Actions)
Child actions是在一個視圖内被調用的Action方法,這可以讓我們在多個頁面重用控制器邏輯并包含與正在運作的主要action不相關的資料。我在SportsStore項目使用過這個技術,當時用作每個頁面的導航菜單。
建立一個Child action如下:

好了,關于是視圖的筆記到這裡就做完了,後面是關于Model的内容。
晚安!