ASP.NET Core 5.0 MVC中的 Razor 頁面 介紹

明志德道發表於2021-01-30

 

Razor 是一個用於將基於伺服器的程式碼嵌入到網頁中的標記語法。 Razor語法由 Razor 標記、c # 和 HTML 組成。 通常包含 Razor 的檔案的副檔名 cshtml

Razor 語法

Razor 支援 c #,並使用 @ 符號從 HTML 轉換為 c #。 Razor 計算 c # 表示式並在 HTML 輸出中呈現。

@ 符號後跟 Razor 保留關鍵字時,它會轉換為 Razor 特定標記。 否則會轉換為純 C#。

該程式碼在 HTML 中使用單個 @ 符號呈現:

<p>@Username</p>

包含電子郵件地址的 HTML 屬性和內容不將 @ 符號視為轉換字元。 以下示例中的電子郵件地址將通過分析來保持不變 Razor :

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

若要對 @ 標記中的符號進行轉義 Razor ,請使用第二個 @ 符號:

<p>@@Username</p>

隱式 Razor 表示式

隱式 Razor 表示式以開頭, @ 後跟 c # 程式碼:

隱式表示式不能包含空格,但 C# await 關鍵字除外。 如果該 C# 語句具有明確的結束標記,則可以混用空格:

 <p>@await DoSomething("hello", "world")</p>

隱式表示式 不能 包含 C# 泛型,因為括號 (<>) 內的字元會被解釋為 HTML 標記。 以下程式碼 效:

<p>@GenericMethod<int>()</p>

上述程式碼生成與以下錯誤之一類似的編譯器錯誤:

  • "int" 元素未結束。 所有元素都必須自結束或具有匹配的結束標記。

  • 無法將方法組 "GenericMethod" 轉換為非委託型別 "object"。 是否希望呼叫此方法?`

泛型方法呼叫必須在顯式 Razor 表示式 Razor 程式碼塊中進行包裝。

顯式 Razor 表示式

顯式 Razor 表示式由 @ 帶對稱括號的符號組成。 若要呈現上週的時間,請 Razor 使用以下標記: 

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>
將計算 @() 括號中的所有內容,並將其呈現到輸出中。

前面部分中所述的隱式表示式通常不能包含空格。 在下面的程式碼中,不會從當前時間減去一週:

<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>

該程式碼呈現以下 HTML:

<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>

可以使用顯式表示式將文字與表示式結果串聯起來:

@{
    var joe = new Person("Joe", 33);
}
​
<p>Age@(joe.Age)</p>
如果不使用顯式表示式,<p>Age@joe.Age</p> 會被視為電子郵件地址,因此會呈現 <p>Age@joe.Age</p>。 如果編寫為顯式表示式,則呈現 <p>Age33</p>

顯式表示式可用於從 .cshtml 檔案中的泛型方法呈現輸出。 以下標記顯示瞭如何更正之前出現的由 C# 泛型的括號引起的錯誤。 此程式碼以顯式表示式的形式編寫:

 <p>@(GenericMethod<int>())</p>

表示式編碼

計算結果為字串的 C# 表示式採用 HTML 編碼。 計算結果為 IHtmlContent 的 C# 表示式直接通過 IHtmlContent.WriteTo 呈現。 計算結果不為 IHtmlContent 的 C# 表示式通過 ToString 轉換為字串,並在呈現前進行編碼。

@("<span>Hello World</span>")
前面的程式碼呈現以下 HTML: 
&lt;span&gt;Hello World&lt;/span&gt;

HTML 在瀏覽器中顯示為純文字:

<跨越 > Hello World < /span>

 

HtmlHelper.Raw 輸出不進行編碼,但呈現為 HTML 標記。

警告

對未經審查的使用者輸入使用 HtmlHelper.Raw 會帶來安全風險。 使用者輸入可能包含惡意的 JavaScript 或其他攻擊。 審查使用者輸入比較困難。 應避免對使用者輸入使用 HtmlHelper.Raw

 @Html.Raw("<span>Hello World</span>")

該程式碼呈現以下 HTML:

 <span>Hello World</span>


Razor 程式碼塊

Razor 程式碼塊以開頭 @ ,並由括起來 {} 程式碼塊內的 C# 程式碼不會呈現,這點與表示式不同。 一個檢視中的程式碼塊和表示式共享相同的作用域並按順序進行定義:

@{
    var quote = "The future depends on what you do today. - Mahatma Gandhi";
}
​
<p>@quote</p>
​
@{
    quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}
​
<p>@quote</p>
該程式碼呈現以下 HTML:
<p>The future depends on what you do today. - Mahatma Gandhi</p>
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>

在程式碼塊中,使用標記將本地函式宣告為用作模板化方法:

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
​
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}
該程式碼呈現以下 HTML:
<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

隱式轉換

程式碼塊中的預設語言是 c #,但 Razor 頁面可轉換回 HTML:

@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

帶分隔符的顯式轉換

若要定義應呈現 HTML 的程式碼塊的子節,請將字元括在標記後 Razor <text>

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <text>Name: @person.Name</text>
}

使用此方法可呈現未被 HTML 標記括起來的 HTML。 如果沒有 HTML 或 Razor 標記,則 Razor 會發生執行時錯誤。

<text> 標記可用於在呈現內容時控制空格:

  • 僅呈現 <text> 標記之間的內容。

  • <text> 標記之前或之後的空格不會顯示在 HTML 輸出中。

顯式行轉換

要在程式碼塊內以 HTML 形式呈現整個行的其餘內容,請使用 @: 語法:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    @:Name: @person.Name
}
如果 @: 程式碼中沒有,則 Razor 會生成執行時錯誤。

@檔案中的額外字元 Razor 可能會導致在塊中後面的語句中出現編譯器錯誤。 這些編譯器錯誤可能難以理解,因為實際錯誤發生在報告的錯誤之前。 將多個隱式/顯式表示式合併到單個程式碼塊以後,經常會發生此錯誤。

控制結構

控制結構是對程式碼塊的擴充套件。 程式碼塊的各個方面(轉換為標記、內聯 C#)同樣適用於以下結構:

條件語句 @if, else if, else, and @switch

@if 控制何時執行程式碼:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
elseelse if 不需要 @ 符號:
@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
else if (value >= 1337)
{
    <p>The value is large.</p>
}
else
{
    <p>The value is odd and small.</p>
}

以下標記展示如何使用 switch 語句:

@switch (value)
{
    case 1:
        <p>The value is 1!</p>
        break;
    case 1337:
        <p>Your number is 1337!</p>
        break;
    default:
        <p>Your number wasn't 1 or 1337.</p>
        break;
}

迴圈語句 @for, @foreach, @while, and @do while

可以使用迴圈控制語句呈現模板化 HTML。 若要呈現一組人員:

@{
    var people = new Person[]
    {
          new Person("Weston", 33),
          new Person("Johnathon", 41),
          ...
    };
}

支援以下迴圈語句:

@for
@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}
@foreach
@foreach (var person in people)
{
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}
@while
@{ var i = 0; }
@while (i < people.Length)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
​
    i++;
}
@do while
@{ var i = 0; }
@do
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
​
    i++;
} while (i < people.Length);

複合語句 @using

在 C# 中,using 語句用於確保釋放物件。 在中 Razor ,使用相同的機制來建立包含其他內容的 HTML 幫助器。 在下面的程式碼中,HTML 幫助程式使用 @using 語句呈現 <form> 標記: 

@using (Html.BeginForm())
{
    <div>
        Email: <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

@try, catch, finally

異常處理與 C# 類似:

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

@lock

Razor 能夠用 lock 語句保護關鍵部分:

@lock (SomeLock)
{
    // Do critical section work
}

說明

Razor 支援 c # 和 HTML 註釋:

@{
    /* C# comment */
    // Another C# comment
}
<!-- HTML comment -->

該程式碼呈現以下 HTML:

<!-- HTML comment -->
Razor 在呈現網頁之前,伺服器將刪除註釋。 Razor 用於 @* *@ 分隔註釋。 以下程式碼已被註釋禁止,因此伺服器不呈現任何標記:
@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

指令

Razor 指令由帶有符號後的保留關鍵字的隱式表示式表示 @ 。 指令通常用於更改檢視分析方式或啟用不同的功能。

@attribute

@attribute 指令將給定的屬性新增到生成的頁或檢視的類中。 以下示例新增 [Authorize] 屬性:

@attribute [Authorize]

@code

此方案僅適用於 Razor ( razor) 的元件。

@code塊使 Razor 元件可以將 c # 成員新增 () 到元件的欄位、屬性和方法:

@code {
    // C# members (fields, properties, and methods)
}
對於 Razor 元件, @code 是的別名, @functions 建議使用 @functions 。 允許多個 @code 塊。

@functions

@functions 指令允許將 C# 成員(欄位、屬性和方法)新增到生成的類中:

@functions {
    // C# members (fields, properties, and methods)
}

Razor 元件中,使用 @code Over @functions 來新增 c # 成員。

例如:


@functions {
    public string GetHello()
    {
        return "Hello";
    }
}

<div>From method: @GetHello()</div> 

該程式碼生成以下 HTML 標記:

<div>From method: Hello</div>

下面的程式碼是生成的 Razor c # 類:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;
​
public class _Views_Home_Test_cshtml : RazorPage<dynamic>
{
    // Functions placed between here 
    public string GetHello()
    {
        return "Hello";
    }
    // And here.
#pragma warning disable 1998
    public override async Task ExecuteAsync()
    {
        WriteLiteral("\r\n<div>From method: ");
        Write(GetHello());
        WriteLiteral("</div>\r\n");
    }
#pragma warning restore 1998

@functions 方法有標記時,會用作模板化方法:

@{
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}
​
@functions {
    private void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
}
該程式碼呈現以下 HTML:
<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@implements

@implements 指令為生成的類實現介面。

以下示例實現 System.IDisposable,以便可以呼叫 Dispose 方法:

@implements IDisposable

<h1>Example</h1>

@functions {
    private bool _isDisposed;

    ...

    public void Dispose() => _isDisposed = true;
}

@inherits

@inherits 指令對檢視繼承的類提供完全控制:

 @inherits TypeNameOfClassToInheritFrom

 

下面的程式碼是一個自定義的 Razor 頁型別:

using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
{
    public string CustomText { get; } = 
        "Gardyloo! - A Scottish warning yelled from a window before dumping" +
        "a slop bucket on the street below.";
}

CustomText 顯示在檢視中:

@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>

該程式碼呈現以下 HTML:

<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>
@model@inherits 可在同一檢視中使用。 @inherits 可位於檢視匯入的 _ViewImports.cshtml 檔案中:
@inherits CustomRazorPage<TModel>
下面的程式碼是一種強型別檢視:
@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>
如果在模型中傳遞“rick@contoso.com”,檢視將生成以下 HTML 標記:
<div>The Login Email: rick@contoso.com</div>
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@inject

@inject指令使 Razor 頁面可以將服務從服務容器注入到檢視。 有關詳細資訊,請參閱檢視中的依賴關係注入

@layout

此方案僅適用於 Razor ( razor) 的元件。

@layout指令指定 Razor 具有指令的可路由元件的佈局 @page 。 佈局元件用於避免程式碼重複和不一致。 有關詳細資訊,請參閱 ASP.NET Core Blazor 佈局

@model

此方案僅適用於 Razor () 的 MVC 檢視和頁面。

@model 指令指定傳遞到檢視或頁面的模型型別:

@model TypeNameOfModel
在 Razor 使用單獨的使用者帳戶建立的 ASP.NET CORE MVC 或頁面應用中, Views/Account/Login。 cshtml 包含以下模型宣告:
@model LoginViewModel
生成的類繼承自 RazorPage<dynamic>
public class _Views_Account_Login_cshtml : RazorPage<LoginViewModel>
Razor 公開 Model 用於訪問傳遞到檢視的模型的屬性:
<div>The Login Email: @Model.Email</div>

@model 指令指定 Model 屬性的型別。 該指令將 RazorPage<T> 中的 T 指定為生成的類,檢視便派生自該類。 如果未指定 @model 指令,則 Model 屬性的型別為 dynamic。 有關詳細資訊,請參閱強型別模型和 @model 關鍵字

@namespace

@namespace 指令:

  • 設定生成的 Razor 頁、MVC 檢視或元件的類的名稱空間 Razor 。

  • 在目錄樹中最近的匯入檔案中設定頁面、檢視或元件類的根派生名稱空間, _ViewImports) 或 _Imports razor (元件) (檢視或頁面。 Razor

    @namespace Your.Namespace.Here

對於 Razor 下表中所示的頁面示例:

  • 每個頁面都匯入 Pages/_ViewImports.cshtml。

  • Pages/_ViewImports.cshtml 包含 @namespace Hello.World

  • 每個頁面都有 Hello.World,作為其名稱空間的根。

名稱空間
Pages/Index. cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Hello.World.MorePages.EvenMorePages

上述關係適用於匯入與 MVC 檢視和元件一起使用的檔案 Razor 。

當多個匯入檔案具有 @namespace 指令時,最靠近目錄樹中的頁面、檢視或元件的檔案將用於設定根名稱空間。

如果前面示例中的 EvenMorePages 資料夾具有包含 @namespace Another.Planet 的匯入檔案(或 Pages/MorePages/EvenMorePages/Page.cshtml 檔案包含 @namespace Another.Planet),則結果如下表所示。

名稱空間
Pages/Index. cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Another.Planet

@page

@page 指令具有不同的效果,具體取決於其所在檔案的型別。 指令:

@preservewhitespace

此方案僅適用於 Razor (.razor) 的元件。

如果設定為 false (預設) ,則將在 Razor 以下情況下刪除從元件 () 中呈現的標記中的空白 .razor

  • 元素中的前導或尾隨空白。

  • RenderFragment 引數中的前導或尾隨空白。 例如,傳遞到另一個元件的子內容。

  • 在 C# 程式碼塊(例如 @if@foreach)之前或之後。

@section

此方案僅適用於 Razor () 的 MVC 檢視和頁面。

@section指令與MVC 和 Razor 頁面佈局結合使用,以使檢視或頁面能夠在 HTML 頁面的不同部分中呈現內容。 有關詳細資訊,請參閱 ASP.NET Core 中的佈局

@using

@using 指令用於向生成的檢視新增 C# using 指令:

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>
在 " Razor 元件" 中, @using 還控制哪些元件在範圍內。

指令屬性

Razor 指令特性由帶有符號後的保留關鍵字的隱式表示式表示 @ 。 指令特性通常會改變元素的分析方式,或實現不同的功能。

@attributes

此方案僅適用於 Razor ( razor) 的元件。

@attributes 允許元件呈現未宣告的屬性。 有關詳細資訊,請參閱 建立和使用 ASP.NET Core Razor 元件

@bind

此方案僅適用於 Razor ( razor) 的元件。

元件中的資料繫結通過 @bind 屬性實現。 有關詳細資訊,請參閱 ASP.NET Core Blazor 資料繫結

@on{EVENT}

此方案僅適用於 Razor ( razor) 的元件。

Razor 為元件提供事件處理功能。 有關詳細資訊,請參閱 ASP.NET Core Blazor 事件處理

@on{EVENT}:preventDefault

此方案僅適用於 Razor ( razor) 的元件。

禁止事件的預設操作。

@on{EVENT}:stopPropagation

此方案僅適用於 Razor ( razor) 的元件。

停止事件的事件傳播。

@key

此方案僅適用於 Razor ( razor) 的元件。

@key 指令屬性使元件比較演算法保證基於鍵的值保留元素或元件。 有關詳細資訊,請參閱 建立和使用 ASP.NET Core Razor 元件

@ref

此方案僅適用於 Razor ( razor) 的元件。

元件引用 (@ref) 提供了一種引用元件例項的方法,以便可以向該例項發出命令。 有關詳細資訊,請參閱 建立和使用 ASP.NET Core Razor 元件

@typeparam

此方案僅適用於 Razor ( razor) 的元件。

@typeparam 指令宣告生成的元件類的泛型型別引數。 有關詳細資訊,請參閱 ASP.NET Core Blazor 模板化元件

模板化 Razor 委託

Razor 模板允許使用以下格式定義 UI 程式碼段:

 @<tag>...</tag>

下面的示例演示如何將模板化 Razor 委託指定為 Func 。 為委託封裝的方法的引數指定動態型別。 將物件型別指定為委託的返回值。 該模板與 Pet(具有 Name 屬性)的 List 一起使用。

public class Pet
{
    public string Name { get; set; }
}
 

@{
    Func<dynamic, object> petTemplate = @<p>You have a pet named <strong>@item.Name</strong>.</p>;
​
    var pets = new List<Pet>
    {
        new Pet { Name = "Rin Tin Tin" },
        new Pet { Name = "Mr. Bigglesworth" },
        new Pet { Name = "K-9" }
    };
}
使用 foreach 語句提供的 pets 呈現該模板: 
@foreach (var pet in pets)
{
    @petTemplate(pet)
}
呈現的輸出: 
<p>You have a pet named <strong>Rin Tin Tin</strong>.</p>
<p>You have a pet named <strong>Mr. Bigglesworth</strong>.</p>
<p>You have a pet named <strong>K-9</strong>.</p>

你還可以將內聯 Razor 模板作為引數提供給方法。 在下面的示例中, Repeat 方法接收 Razor 模板。 該方法使用模板生成 HTML 內容,其中包含列表中提供的重複項: 

@using Microsoft.AspNetCore.Html
​
@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();
​
        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }
​
        return html;
    }
}

  

使用前面示例中的 pets 列表,呼叫 Repeat 方法以及:

  • PetList

  • 每隻寵物的重複次數。

  • 用於無序列表的列表項的內聯模板。 

<ul>
    @Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

呈現的輸出: 

<ul>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>K-9</li>
    <li>K-9</li>
    <li>K-9</li>
</ul>

 標記幫助程式

此方案僅適用於 Razor () 的 MVC 檢視和頁面。

標記幫助程式有三個相關指令。

指令函式
@addTagHelper 向檢視提供標記幫助程式。
@removeTagHelper 從檢視中刪除以前新增的標記幫助程式。
@tagHelperPrefix 指定標記字首,以啟用標記幫助程式支援並闡明標記幫助程式的用法。

-------------------------------------------------------

相關文章