\t\t介紹“Razor”— ASP.NET的一個新視圖引擎

設計目標

在設計和評估“Razor”時,我們牢記以下幾個目標:

· 緊湊、富有表現力和流暢:Razor儘量減少一個文件裏需要敲入的字符數,給你暢快淋漓的編碼體驗。與大部分模板的語法不同,你不會因爲需要在HTML中標註服務器端代碼塊而中斷敲代碼的快感。代碼分析器足夠聰明,能夠從你的代碼裏推斷出是否爲服務器端代碼。這使得其簡潔、富有表現力的語法輸入能夠乾淨,快速,有趣。

· 上手快: Razor非常容易上手,你只需要瞭解很少的新東西就可以掌握它,使用你現有的編程語言和HTML知識就足夠了。

· 不是一個新的編程語言:我們儘量避免爲Razor創建一個新的命令式語言。相反,我們希望讓程序員只使用現有的C#/VB(或其它)編程語言知識就能使用Razor,我們只不過在你選擇的編程語言裏,提供一個非常棒的基於模板生成HTML的標記語法。

· 可以使用任何文本編輯器編寫:Razor不要求什麼特別的工具,使用老古董的文本編輯器也可以高效編程(“記事本”就不錯)。

· 很好的智能感應輸入提示:雖然Razor不是專爲某個工具或者代碼編輯器設計的,但它在Visual Studio裏還是有很讚的智能提示功能。我們將會升級Visual Studio 2010和Visual Web Developer 2010使得它具有完整的編輯器智能提示功能。

· 便於單元測試:新的視圖引擎支持對視圖執行單元測試,不需要控制器(controller)或者Web服務器,而且可以包含在任意的單元測試項目中—不需要單獨的應用程序域(App-Domain)。

過去幾個月,我們一直在用Razor來編寫程序,並邀請了一些志願者(包括好幾組非.NET的 Web程序員)來做易用性研究。使用過它的人對它的評價都不錯。

彈性的選擇空間

ASP.NET最讚的地方之一就是大部分組件都是可插拔的。如果你發現有一個組件不好用,隨時都可以換成另外一個。

ASP.NET MVC的下一個版本將會包括一個新的“添加->視圖”對話框,它讓你可以方便地在創建新的視圖模板文件時選擇你想要使用的語法。它還便於你選擇任一個安裝在機器上的視圖引擎—選擇你感覺最自然的視圖方案:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

Razor將會是ASP.NET MVC內置的視圖引擎之一。所有的視圖輔助(helper)方法和編程模型特性同時支持Razor和.ASPX視圖引擎。

你還將可以在單個站點或程序中混合使用多個視圖引擎寫的視圖模板。比如說,你可以編寫一些視圖,有些用.aspx文件,有些用.cshtml或者.vbhtml文件(分別是Razor的C#和VB版本的文件後綴名),而另外一些用Spark或者NHaml。你還可以在採用一種視圖引擎的視圖模板裏包含用另一種引擎編寫的局部視圖模板。總之,你有靈活的選擇空間。

Razor版的“Hello World”

Razor允許你從靜態的HTML頁面(或者任意的文本內容)開始,添加服務器端代碼使其變成動態頁面。Razor的一個核心設計理念就是使編碼過程更加流暢,並且只要最少的按鍵次數就能快速地在HTML標記中添加服務器端代碼。

讓我們來創建一個簡單的例子:“hello world”,它的最終輸出如下圖所示:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

使用.ASPX“代碼碎塊[ii]”的方式編寫

如果用現有ASP.NET的.ASPX標記語法來編寫上面的“Hello World”示例的話,我們需要在HTML標籤中使用”<%= %>”來標記“代碼碎塊”:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

仔細觀察就可以發現上例中每一個代碼碎塊都需要5個字符(”<%= %>”)來標明代碼的開始和結束位置。而且其中還有幾個字符在鍵盤上不是特別好敲到(特別是“%”鍵—它位於大部分鍵盤的中上部)。

使用Razor的語法編寫

在Razor中,你只需要用一個”@”字符就可以標識代碼塊的開始,與”<% %>”代碼碎塊不一樣,Razor不需要你顯式指明代碼塊的結束位置:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

Razor分析器懂得代碼塊中使用的C#或VB的語法—這就是爲什麼上例中我們不需要顯式關閉代碼塊的原因。Razor可以自動識別出上面的語句是獨立的代碼塊並悄悄地爲我們關閉它們。

看看,即使是像“hello world”這樣微不足道的例子就爲我們節省了12次鍵盤敲擊。而且在鍵盤上”@”字符還比”%”字符更容易按,敲起來更快也更流暢。

循環和內嵌HTML示例

讓我們來看看另外一個簡單的場景,比如說要列出一些商品(並在每樣商品旁標明價格):

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

用.ASPX”代碼碎塊”編寫

如果用ASP.NET現有的.ASPX標記語法,我們可能需要寫類似下面的代碼來動態生成一個<ul>列表,裏面包含表示每個商品的<li>元素:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

使用Razor語法

下面是生成同樣輸出的Razor版本的代碼:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

請注意上面”@”符號是如何開始一個“foreach”循環,並在循環內嵌入一行包含代碼塊的HTML語句的。因爲Razor分析器知道我們在代碼塊裏用的C#語法,它可以識別出<li>標籤裏的內容應該被包含在foreach代碼塊中,並循環處理它們。它甚至還知道末尾的“}”結束foreach循環。

Razor很聰明,還能識別出<li>標籤內的@p.Name和@p.Price是服務器端代碼—並且在每次循環時執行它們。另外請留心Razor在HTML和代碼混合的情況下,還能推導出@p.Name和@p.Price代碼塊的結束位置。

不需要在你的模板中添加許許多多打開/關閉標記來編寫代碼的感覺果然是酣暢淋漓。

If代碼塊和多行語句

下面是其他幾個常見的場景:

If語句

跟上面的foreach示例一樣,你可以在if語句中直接嵌入內容(或其他C#或者VB語言元素),而不需要顯式指明代碼塊的開始和結束位置。例如:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

多行語句

你可以像下面這樣,使用“@{ 代碼 }” 標註多行語句:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

請注意上例中,變量可以被多個代碼塊引用—變量“message”在包含多行語句的“@{}”塊中定義,但也可以被@message代碼塊使用。這個跟.aspx文件裏的”<% %>”和”<%= %>”的語法類似。

多符號語句

“@()”語法允許代碼塊中有多個符號,例如,我們可以把上例中連接字符串和數字的代碼使用”@ ()” 代碼塊這樣重寫:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

集成代碼和內容

Razor解析器內置了很多語言智能—髒活累活幫你做。

在HTML裏,它會不會影響”@”符號在電子郵件地址和其他地方的用法?

大部分情況下,Razor解析器都有足夠的能力推導出模板裏的一個“@”字符到底是在代碼中用到,還是在靜態內容中用到。例如,我在下例中的郵件地址中使用了”@”字符:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

當解析文件時,Razor會分析”@”字符右邊的內容來判斷它到底是代碼(如果是CSHTML文件的話那就是C#代碼,而如果是VBHTML文件的話那就是VB代碼)還是靜態文本內容。上例中的代碼會輸出以下的HTML(郵件地址被當作靜態內容輸出,而@DateTime.Now就被當作代碼執行了):

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

如果碰到和代碼一樣格式的內容(或者你想把代碼當作內容看待),你可以顯式地打@@來用另外一個”@”字符進行轉義。

識別內嵌的內容

當在一個if/else,foreach或者其他塊語句中內嵌HTML文本時,可以考慮用一個HTML或XML標籤將嵌套內容環繞起來,這樣可以更清楚地標明一個文本內容塊的開始。

例如,下例我使用<span>標籤包圍多行文本內容,而文本里還有一個代碼塊:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

在客戶端的顯示結果如下—注意那個<span>標籤:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

如果你不想在顯示文本內容時,把外面的標籤也輸出到客戶端,那可以考慮使用<text>將嵌套內容括起來:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

上面的代碼在客戶端的輸出結果如下—請注意外面的<text>標籤沒有被輸出:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

HTML編碼

默認情況下,”@”語句塊生成的內容會自動對HTML代碼進行過濾和轉換[Yimin1] ,用來更好地防範XSS垮站腳本攻擊。

版面設計/母版頁的情況—基礎篇

在站點中保持一致的頁面觀感風格非常重要。ASP.NET 2.0引入了“母版頁面(master page)”的概念,就是用來幫助在使用基於.aspx的頁面或模板時實現這個功能。Razor同樣也支持這個概念,它用的是“版面設計頁面(layout pages)”—你可以先定義一個通用的站點模板,然後在站點其他視圖或頁面繼承模板定義的統一觀感。

版面設計的一個簡單示例

下面是一個簡單的版面設計頁面示例,文件將會被保存爲“SiteLayout.cshtml”。它包含了所有要放在頁面裏的靜態HTML文本內容和動態的服務器端代碼。接着我們添加了一個名爲“RenderBody()”的輔助函數,放在模板中需要根據所請求的URL而“填入”具體內容的地方:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

接下來我們再創建一個名爲“Home.cshtml”的視圖模板,它只包含了必要的文本內容和代碼來構成所請求頁面的具體內容,外圍的內容則由版面模板提供:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

請留意上面在Home.cshtml文件中我們怎麼來顯式地設置“LayoutPage”屬性。它指明瞭我們期望用SiteLayout.cshtml作爲這個視圖的版面設計模板。我們還可以在ASP.NET MVC 控制器(Controller)調用Home.cshtml這個視圖模板的時候,可以指定這個版面設計文件,或者將其配置爲站點默認的版面設計模板(這種情況下,我們只需要在項目中的一個文件中指定它,而所有的視圖模板都會自動採用它)。

當我們將Home.cshtml作爲一個視圖模板顯示時,它會合並版面設計頁和子頁面的內容,然後將下面的內容發送到客戶端:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

簡潔、清晰、富有表現力的代碼

上例中值得注意地方的還有一點,就是版面定義和在視圖/頁面中使用它們的語法既清晰又簡練。上面列出的SiteLayout.cshtml和Home.cshtml代碼截圖已經包含了兩個文件所有的代碼—沒有額外的配置步驟或冗餘的標籤,沒有<%@ Page %>前綴,也不需要設置其它的標籤或者屬性。

我們盡力使編寫出來的代碼簡潔流暢。我們還希望任何人都可以在一個文本編輯程序中打開、編輯和調整/自定義它們。不需要代碼生成或者智能提示(Intellisense)。

版面設計頁面/母版頁的情況—覆寫部分內容

版面設計頁面可以有選擇性地定義幾個不同的“節”,允許基於這個版面設計的視圖模板通過“填入”自定義的內容來覆寫它。這就允許你在視圖中覆寫版面設計頁裏不連續的內容段落,從而使你的站點版面設計更有彈性。

例如,我們回到SiteLayout.cshtml文件,並在其中定義兩個節,這樣視圖模板可以有選擇性的填充這兩個節。我們將節的名稱命名爲“menu”和“footer”—然後在RenderSection()輔助函數傳入optional=true這個參數來表明它們是可選填充節(我們可以用C#最新的optional參數語法來做這件事情,我在前面的博客裏也提到了這個用法)。

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

因爲兩個節被標記成了“可選”,不需要在Home.cshtml文件中定義它們。即使沒有它們,站點依然可以正常工作。

讓我們回到Home.cshtml並自定義Menu和Footer節。下面的截圖包含了Home.cshtml裏所有的內容—再沒有其它內容了。注:我已經把LayoutPage設置爲站點範圍的默認模板了—所以它沒有顯示在裏面。

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

我們覆寫的”menu”和“footer”節定義在文件裏的以相應的名字命名的@section { }塊裏面。我們刻意不要求你在節裏包含“main/body”內容,相反將它們內聯在頁面裏(除了節省鍵盤敲擊的次數以外,還便於你在版面設計頁面中添加新的節以後,不需要再回去修改所有已有頁面的語法)。

當再次將Home.cshtml以視圖模板的形式顯示的時候,它現在會合並版面設計頁和子頁面裏的內容,並將兩個自定義節覆寫的內容整合進來,最終發送到客戶端的內容如下:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

封裝和重用HTML輔助函數

我們剛剛講過如何使用版面設計頁給站點提供統一的觀感。現在讓我們看看如何通過創建可複用的“HTML輔助函數”來把生成HTML的功能封裝成一個函數庫,這樣可以在整個站點複用—甚至在多個站點複用。

基於代碼的HTML輔助函數

ASP.NET MVC有一個“HTML輔助函數”的概念—封裝了生成HTML的邏輯並可以用在代碼塊裏的函數。它們當前還都是純粹通過代碼實現的,一般通過擴展函數(Extension Method)實現。現有的所有內置在ASP.NET MVC裏的HTML擴展函數都可以使用在“Razor”視圖引擎裏(不需要修改任何代碼):

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

聲明式的HTML輔助函數

使用純代碼的類來生成HTML可以工作—但不是很理想。

我們來看Razor的另外一個特性,使用簡單的更具描述性的方法創建可複用的HTML輔助函數。我們計劃讓你可以使用類似下面的 @helper { }聲明式語法創建可複用的輔助函數:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

你將可以把包含有這種輔助函數的.cshtml文件放到一個Views\Helpers文件夾,然後就可以在站點上使用它們了(再沒有其它的步驟了):

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

請注意上例中我們可以爲ProductListing()函數定義參數。這樣你就可以爲函數傳入任意的參數了(而且還能完全利用可選參數,nullable類型,範型等現有編程語言的特性),另外還有Visual Studio強大的調試支持。

注:@helper語法在Razor的第一個beta版裏還沒有—但我們希望能在下一個發佈裏把它包含進來。基於代碼的輔助函數在第一個Beta版本里就可以使用。

傳入內聯模板作爲參數

Razor中另一個很有用(或者可以說是相當了得)的功能就是允許向輔助函數傳入“內聯模板”參數。這些“內聯模板”可以同時包含HTML和代碼,而且可以被輔助函數即行調用。

下例中的“Grid”HTML輔助函數就是通過這種技術在客戶端呈現一個DataGrid:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

上例中Grid.Render()函數調用使用的是C#語法。我們使用了新的語法—C#命名參數把強類型的參數傳給Grid.Render函數。這同時也意味着我們可以使用全部智能提示,還有編譯時的語法檢查功能。

在定義列的時候傳給“format”參數的就是一個“內聯模板”—它同時包含了自定義的html和代碼,它們是用來自定義數據的顯示方式的。更厲害的是,Grid輔助函數可以把我們的 “內聯模板”當作一個委託來調用,想幾時調用就幾時調用,想調用多少次就調用多少次。在上面的場景裏,每呈現grid的一行,就會調用它一次—並通過傳入“item”變量,以便我們的模板可以顯示恰當的內容。

這個功能允許你開發功能更強大的HTML輔助函數。今後你既可以使用代碼方式(跟現在創建擴展函數的方式一樣),也可以使用聲明式的@helper { }方式來編寫HTML輔助函數。

對Visual Studio的支持

前面說過,Razor的一個目標就是儘量減少鍵盤敲擊次數,而且使用普通的文本編輯器就可以編寫(記事本就很不錯了)。我們通過保證語法清晰簡單幹練來實現這個目標。

Visual Studio也支持Razor, 使你在裏面編寫Razor代碼時感覺更豐富。對於基於Razor的源文件,我們提供了完整的HTML、JavaScript和C#/VB代碼智能提示功能:

介紹“Razor”— ASP.NET的一個新視圖引擎 - yandavid - 我的博客

請注意,上面我們甚至爲嵌入在foreach循環體裏面<li>元素的Product對象的“@p.”啓用了智能提示。另外還要注意的地方是,在“解決方案資源管理器”的“\View”文件夾裏,同時存放了.aspx和.cshtml視圖模板。你可以在單個程序中使用多個視圖引擎—便於你選擇最適合你的引擎。

總結

我們認爲“Razor”是一個非常好的新的視圖引擎,它提供了流暢的專注於代碼的模版方案。它的編碼工作流快速、富有表現力並有趣。語法簡練並節省按鍵次數,同時還提升了代碼的可讀性。它會作爲內置的視圖引擎並隨下一個版本的ASP.NET MVC發佈。你也可以把單獨的.cshtml/.vbhtml放到程序裏,並把它們當作獨立的頁面執行—這樣你就也可以在ASP.NETWeb窗體程序中使用它了。

發佈了190 篇原創文章 · 獲贊 4 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章