ASP.NET MVC 3 開始提供的 Razor V1 改變了以往使用 WebFormView 的寫作習慣,讓我們在 檢視頁面 (View Page) 中的 HTML 與伺服器端的語法 (Razor) 混和得更漂亮,不再有醜陋的 <% … %> 符號了。然而從 ASP.NET MVC 4 開始,在 Razor 推出了第二版,有許多增強的特性,本篇文章將介紹這些增強的特性。而到了 ASP.NET MVC 5 推出了 Razor V3 版,這版只有修正一些程式錯誤,並沒有功能增強。
由於使用 Razor 語法的檢視頁面,背後採用的是 ASP.NET Web Pages 技術,整個頁面都會交由 ASP.NET Web Pages 進行控管。而事實上,Razor 頁面則是一種「動態編譯」的技術,當 ASP.NET MVC 網站在執行的時候,會自動監視所有 *.cshtml 檔案的變更,只要有偵測到檔案異動,就會自動重新產生新的、相對應的 *.cs 程式碼,預設這些動態產生的程式碼會被寫入到 Temporary ASP.NET Files 資料夾下,可能的路徑有:
- 執行在 x64 架構下:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files - 執行在 x86 架構下:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files
這個暫存路徑其實也可以透過 web.config 進行設定,設定的範例如下:
<system.web>
<compilation tempDirectory="G:\TempASP.NETFiles\">
...
</compilation>
</system.web>
若你想看看這些 Razor 頁面產生的 *.cs 檔案在哪,你可以隨便找一張 View 並在 Razor 頁面的最上面第一行加上 @model <> 故意寫出一個錯誤的 Razor 語法,當顯示例外訊息時,就會看到該檔案產生的 *.cs 檔案路徑了,如下圖示:
執行該頁面就會得到以下錯誤,錯誤訊息下方的「原始程式檔」就是這張 Razor 所建立的 *.cs 檔案,檔名當然是一串看不懂的亂碼。
接著你將該程式碼打開,就可以看到完整的 *.cs 檔案:
從這個檔案你就可以大致上猜到 Razor 使怎樣的運作原理:
-
網站執行時,先找出所有 *.cshtml 頁面,並將所有頁面轉換成 *.cs 格式的程式碼。
-
轉換成 *.cs 格式的程式碼的過程中,會解析 Razor 專屬的語法,並轉換成標準的 C# 程式碼。
-
轉換成功後,會交由 C# 編譯器進行程式碼編譯,然後轉成 .NET 組件 (*.dll) 並自動載入到 AppDomain 裡
-
因此 ASP.NET MVC 就可以順利執行這些 Razor 頁面。
所以,ASP.NET MVC 的 Razor 頁面,會有一個轉換成 C# 的過程,也就是說他並不是一個單純的 HTML,而是可以設計出一些好用的功能與特性。例如 ASP.NET MVC 6 開始將會有個 TagHelper 功能,這個功能可以伺服器端的輸出更加「標籤化」,這部分我之後會有專文介紹。
當瞭解了 Razor 的潛力無窮後,我就開始來介紹這些新增的特性:
更強大的 URL 解析能力
早期的 ASP.NET MVC 要在 View 裡面載入一個 JavaScript 檔案,必須用以下語法:
現在,你可以很輕鬆地改寫成以下語法:
不僅僅是 JavaScript 而已,只要 HTML 標籤內的任意屬性 (Attributes),都可以使用 ~/ 語法來代表網站根目錄。例如我們用 Angular 的 ng-src 屬性,他也是可以認得的:
不過要特別注意的地方是,如果你用 HTML5 的 data-* 屬性 Razor 是不會幫你轉換 ~/ 的!
以下範例用到的 data-uri 由於屬於 HTML5 的自訂擴充屬性,所以 Razor 預設不會幫你解析 ~/ 這個語法:
條件式屬性輸出 (Conditional Attribute)
我們以一個 HTML 表單欄位為例,假設我們要透過一個
ViewBag.IsAutoFocus 屬性來控制 View 頁面上的某個 input 欄位是否要設定為自動聚焦,我們可以在 input 標籤中加上
autofocus 屬性 (這是 HTML5 的新增屬性),例如:
※ 上述兩行都是有效的 HTML5 語法。
然後要透過 ViewBag.IsAutoFocus 來控制是否輸出 autofocus 屬性,以前就非常麻煩,你可能會這樣寫:
<input type="text" value=""
@if(ViewBag.IsAutoFocus) { <text>autofocus</text> } />
而在 Razor V2 之後,你可以改成以下語法:
@{
ViewBag.IsAutoFocus = true;
}
<input type="text" value="" autofocus="@ViewBag.IsAutoFocus" />
這段輸出的 HTML 將會是:
<input type="text" value="" autofocus="autofocus" />
如果是以下程式,也就是說如果將 ViewBag.IsAutoFocus 改為 false:
@{
ViewBag.IsAutoFocus = false;
}
<input type="text" value="" autofocus="@ViewBag.IsAutoFocus" />
這段輸出的 HTML 將會是:
<input type="text" value="" />
是不是語法漂亮許多呢! ;-)
我還另外在 .NET Fiddle 建立了一個範例,你也可以看看!
基本上這個例子是展示,當你想輸出一個 CSS 的 class 到 HTML 標籤中時,如果該 class 屬性的內容為 null 時,那麼 Razor 將會連同 class 一起隱藏起來,這也算是非常貼心的功能!
相關連結