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

來源:互聯網
上載者:User

我的團隊當前正在從事的工作之一就是為ASP.NET添加一個新的視圖引擎。

一直以來,ASP.NET MVC都支援 “視圖引擎”的概念—採用不同文法的模板的可插拔模組。當前ASP.NET MVC “預設”的視圖引擎是ASP.NET Web表單使用的.aspx/.ascx/.master檔案模板。而當今其他一些流行的ASP.NET MVC視圖引擎還包括Spark和NHaml。

我們正在打造一個新的視圖引擎,它是一個在HTML產生方面進行最佳化,採用專註於代碼的模版解決方案。它的開發代號是“Razor”,第一個beta版本很快就會發布出來。

設計目標

在設計和評估“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 MVC內建的視圖引擎之一。所有的視圖輔助(helper[i])方法和編程模型特性同時支援Razor和.ASPX視圖引擎。

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

Razor版的“Hello World”

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

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

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

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

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

使用Razor的文法編寫

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

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

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

迴圈和內嵌HTML樣本

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

用.ASPX”代碼碎塊”編寫

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

使用Razor文法

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

請注意上面”@”符號是如何開始一個“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語言元素),而不需要顯式指明代碼塊的開始和結束位置。例如:

多行語句

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

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

多符號語句

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

整合代碼和內容

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

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

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

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

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

識別內嵌的內容

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

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

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

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

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

HTML編碼

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

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

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

版面設計的一個簡單樣本

下面是一個簡單的版面設計頁面樣本,檔案將會被儲存為“SiteLayout.cshtml”。它包含了所有要放在頁面裡的靜態HTML常值內容和動態伺服器端代碼。接著我們添加了一個名為“RenderBody()”的輔助函數,放在模板中需要根據所請求的URL而“填入”具體內容的地方:

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

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

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

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

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

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

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

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

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

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

讓我們回到Home.cshtml並自訂Menu和Footer節。下面的包含了Home.cshtml裡所有的內容—再沒有其它內容了。註:我已經把LayoutPage設定為網站範圍的預設範本了—所以它沒有顯示在裡面。

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

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

封裝和重用HTML輔助函數

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

基於代碼的HTML輔助函數

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

聲明式的HTML輔助函數

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

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

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

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

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

傳入內聯模板作為參數

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

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

上例中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代碼智能提示功能:

請注意,上面我們甚至為嵌入在foreach迴圈體裡面<li>元素的Product對象的“@p.”啟用了智能提示。另外還要注意的地方是,在“方案總管”的“\View”檔案夾裡,同時存放了.aspx和.cshtml視圖模板。你可以在單個程式中使用多個視圖引擎—便於你選擇最適合你的引擎。

總結

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

 

轉至:http://blog.joycode.com/scottgu/archive/2010/07/20/116030.joy

======================================

collinye個人看法:razor給程式帶來了方便,更增強代碼的美感,終於可以擺脫“<%%>”,多令人高興的事。明天準備在項目中做一下嘗試。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.