Razor 視圖引擎是 ASP.NET MVC 3 開始擴展的內容,而且也是默認視圖引擎。html
Razor 經過理解標記的結構來實現代碼和標記之間儘量順暢的轉換。下面的例子演示了一個包含少許視圖邏輯的簡單 Razor 視圖:算法
@{
// this is a block of code. For demonstration purposes,
// we'll create a "model" inline.
var items = new string[] { "one", "two", "three" };
}
<html>
<head><title>Sample View</title></head>
<body>
<h1>Listing @items.Length items.</h1>
<ul>
@foreach (var item in items)
{
<li>The item name is @item.</li>
}
</ul>
</body>
</html>
代碼示例使用了 C# 語法,這就意味着文件的擴展名是 .cshtml。同理,使用 Visual Basic 語法的 Razor 視圖的擴展名將是 .vbhtml。這些擴展名很重要,由於它們指出了 Razor 語法分析器的編碼語言的語法。app
<h1>Listing @items.Length items.</h1> this
Razor 中的核心轉換字符是「@」符號。且十分智能,它知道表達式後的空格字符不是一個有效的標識符,因此它可否順暢的轉回到標記語言。編碼
<li>The item name is @item.</li>spa
注意,@item 代碼表達式後的「.」是有效的代碼字符,但 Razor 是如何知道表達式後面的「.」不是引用當前表達式的屬性或方法呢?其實,Razor 是向後窺看,看到了一個尖括號,所以知道這不是一個有效的標識符,因此會轉回標記模式。code
簡潔乾淨的語法,有時也會帶來潛在的二義性。以下,想要輸出的結果是「MyApp.Models」,卻出現了錯誤,提示 string 沒有 Models 屬性。在這種邊界狀況下,Razor 沒有理解咱們的意圖。htm
幸虧,Razor 能夠經過將表達式用圓括號括起來以支持顯式代碼表達式:對象
考慮一下電子郵件地址的狀況,乍看之下,這可能會出錯。但 Razor 採用了一個簡單的算法來辨別是不是有效的電子郵件地址。雖然還不是很完美,但卻能夠適用於大多數狀況。blog
<span>support@megacorp.com</span>
Razor 將嘗試解析這些隱式代碼表達式,但會以失敗了結。這種狀況下,應該使用 @@ 符號來轉義 @ 符號。
<p>You should follow @Jack, @Rose</p> // Error
<p>You should follow @@Jack, @@Rose</p>
許多狀況下都須要用視圖顯示用戶輸入,如博客評論或產品評論等,因此老是存在潛在的跨站點腳本注入攻擊(XSS),值得稱讚的是 Razor 表達式是用 HTML 自動編碼的。
@{
string message = "<script>alert('hacked')</script>";
}
<span>@message</span>
這段代碼不會彈出一個警告框,而會呈現編碼的 HTML,查看源文件後代碼以下:
<span><script>alert('hacked')</script></span>
若是想展現 HTML 標記,就返回一個 System.Web.IHtmlString 對象的實例,Razor 就不會對其進行編碼。本文後面要討論的全部視圖輔助類都是返回這個接口的實例,由於它們想在頁面上呈現 HTML。
也可使用 Html.Raw 便捷方法:
<span>@Html.Raw(message)</span>
自動的對用戶輸入進行 HTML 編碼有效緩和了 XSS 的脆弱性,可是對於在 JavaScript 中顯示用戶輸入來講仍是不夠的!
<script>
$(function () {
var message = 'Hello @ViewBag.Username';
$("#message").html(message).show('slow');
});
</script>
若是用戶提供如下的字符串做爲用戶名,HTML 將被設置爲一個腳本標籤:
\x3cscript\x3e%20alert(\x27pwnd\x27)%20\x3c/script\x3e
當在 JavaScript 中將用戶提供的值賦給變量時,要使用 JavaScript 字符串編碼而不單單是 HTML 編碼!記住這一點很重要,也就是要用 @Ajax.JavaScriptStringEncode 方法對用戶輸入進行編碼:
<script>
$(function () {
var message = 'Hello @Ajax.JavaScriptStringEncode(ViewBag.Username)';
$("#message").html(message).show('slow');
});
</script>
這樣就能夠有效的避免 XSS 攻擊!
正如前面所說,尖括號會致使 Razor 轉回標記,所以在調用泛型方法時,整個表達式須要用圓括號括起來:
@(Html.SomeMethod<AType>())