ASP.NET Core 的 Razor 语法参考Razor syntax reference for ASP.NET Core

作者:Rick AndersonLuke LathamTaylor MullenDan VicarelBy Rick Anderson, Luke Latham, Taylor Mullen, and Dan Vicarel

Razor 是一种标记语法,用于将基于服务器的代码嵌入网页中。Razor is a markup syntax for embedding server-based code into webpages. Razor 语法由 Razor 标记、C# 和 HTML 组成。The Razor syntax consists of Razor markup, C#, and HTML. 包含 Razor 的文件通常具有 .cshtml 文件扩展名。Files containing Razor generally have a .cshtml file extension.

呈现 HTMLRendering HTML

默认 Razor 语言为 HTML。The default Razor language is HTML. 从 Razor 标记呈现 HTML 与从 HTML 文件呈现 HTML 并没有什么不同。Rendering HTML from Razor markup is no different than rendering HTML from an HTML file. 服务器会按原样呈现 .cshtml Razor 文件中的 HTML 标记。HTML markup in .cshtml Razor files is rendered by the server unchanged.

Razor 语法Razor syntax

Razor 支持 C#,并使用 @ 符号从 HTML 转换为 C#。Razor supports C# and uses the @ symbol to transition from HTML to C#. Razor 计算 C# 表达式,并将它们呈现在 HTML 输出中。Razor evaluates C# expressions and renders them in the HTML output.

@ 符号后跟 Razor 保留关键字时,它会转换为 Razor 特定标记。When an @ symbol is followed by a Razor reserved keyword, it transitions into Razor-specific markup. 否则会转换为纯 C#。Otherwise, it transitions into plain C#.

若要对 Razor 标记中的 @ 符号进行转义,请使用另一个 @ 符号:To escape an @ symbol in Razor markup, use a second @ symbol:

<p>@@Username</p>

该代码在 HTML 中使用单个 @ 符号呈现:The code is rendered in HTML with a single @ symbol:

<p>@Username</p>

包含电子邮件地址的 HTML 属性和内容不将 @ 符号视为转换字符。HTML attributes and content containing email addresses don't treat the @ symbol as a transition character. Razor 分析不会处理以下示例中的电子邮件地址:The email addresses in the following example are untouched by Razor parsing:

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

隐式 Razor 表达式Implicit Razor expressions

隐式 Razor 表达式以 @ 开头,后跟 C# 代码:Implicit Razor expressions start with @ followed by C# code:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

隐式表达式不能包含空格,但 C# await 关键字除外。With the exception of the C# await keyword, implicit expressions must not contain spaces. 如果该 C# 语句具有明确的结束标记,则可以混用空格:If the C# statement has a clear ending, spaces can be intermingled:

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

隐式表达式不能包含 C# 泛型,因为括号 (<>) 内的字符会被解释为 HTML 标记。Implicit expressions cannot contain C# generics, as the characters inside the brackets (<>) are interpreted as an HTML tag. 以下代码效:The following code is not valid:

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

上述代码生成与以下错误之一类似的编译器错误:The preceding code generates a compiler error similar to one of the following:

  • "int" 元素未结束。The "int" element wasn't closed. 所有元素都必须自结束或具有匹配的结束标记。All elements must be either self-closing or have a matching end tag.
  • 无法将方法组 "GenericMethod" 转换为非委托类型 "object"。Cannot convert method group 'GenericMethod' to non-delegate type 'object'. 是否希望调用此方法?`Did you intend to invoke the method?`

泛型方法调用必须包装在显式 Razor 表达式Razor 代码块中。Generic method calls must be wrapped in an explicit Razor expression or a Razor code block.

显式 Razor 表达式Explicit Razor expressions

显式 Razor 表达式由 @ 符号和平衡圆括号组成。Explicit Razor expressions consist of an @ symbol with balanced parenthesis. 若要呈现上一周的时间,可使用以下 Razor 标记:To render last week's time, the following Razor markup is used:

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

将计算 @() 括号中的所有内容,并将其呈现到输出中。Any content within the @() parenthesis is evaluated and rendered to the output.

前面部分中所述的隐式表达式通常不能包含空格。Implicit expressions, described in the previous section, generally can't contain spaces. 在下面的代码中,不会从当前时间减去一周:In the following code, one week isn't subtracted from the current time:

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

该代码呈现以下 HTML:The code renders the following HTML:

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

可以使用显式表达式将文本与表达式结果串联起来:Explicit expressions can be used to concatenate text with an expression result:

@{
    var joe = new Person("Joe", 33);
}

<p>Age@(joe.Age)</p>

如果不使用显式表达式,<p>Age@joe.Age</p> 会被视为电子邮件地址,因此会呈现 <p>Age@joe.Age</p>Without the explicit expression, <p>Age@joe.Age</p> is treated as an email address, and <p>Age@joe.Age</p> is rendered. 如果编写为显式表达式,则呈现 <p>Age33</p>When written as an explicit expression, <p>Age33</p> is rendered.

显式表达式可用于从 .cshtml 文件中的泛型方法呈现输出。Explicit expressions can be used to render output from generic methods in .cshtml files. 以下标记显示了如何更正之前出现的由 C# 泛型的括号引起的错误。The following markup shows how to correct the error shown earlier caused by the brackets of a C# generic. 此代码以显式表达式的形式编写:The code is written as an explicit expression:

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

表达式编码Expression encoding

计算结果为字符串的 C# 表达式采用 HTML 编码。C# expressions that evaluate to a string are HTML encoded. 计算结果为 IHtmlContent 的 C# 表达式直接通过 IHtmlContent.WriteTo 呈现。C# expressions that evaluate to IHtmlContent are rendered directly through IHtmlContent.WriteTo. 计算结果不为 IHtmlContent 的 C# 表达式通过 ToString 转换为字符串,并在呈现前进行编码。C# expressions that don't evaluate to IHtmlContent are converted to a string by ToString and encoded before they're rendered.

@("<span>Hello World</span>")

该代码呈现以下 HTML:The code renders the following HTML:

&lt;span&gt;Hello World&lt;/span&gt;

该 HTML 在浏览器中显示为:The HTML is shown in the browser as:

<span>Hello World</span>

HtmlHelper.Raw 输出不进行编码,但呈现为 HTML 标记。HtmlHelper.Raw output isn't encoded but rendered as HTML markup.

警告

对未经审查的用户输入使用 HtmlHelper.Raw 会带来安全风险。Using HtmlHelper.Raw on unsanitized user input is a security risk. 用户输入可能包含恶意的 JavaScript 或其他攻击。User input might contain malicious JavaScript or other exploits. 审查用户输入比较困难。Sanitizing user input is difficult. 应避免对用户输入使用 HtmlHelper.RawAvoid using HtmlHelper.Raw with user input.

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

该代码呈现以下 HTML:The code renders the following HTML:

<span>Hello World</span>

Razor 代码块Razor code blocks

Razor 代码块以 @ 开头,并括在 {} 中。Razor code blocks start with @ and are enclosed by {}. 代码块内的 C# 代码不会呈现,这点与表达式不同。Unlike expressions, C# code inside code blocks isn't rendered. 一个视图中的代码块和表达式共享相同的作用域并按顺序进行定义:Code blocks and expressions in a view share the same scope and are defined in order:

@{
    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:The code renders the following 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>

在代码块中,使用标记将本地函数声明为用作模板化方法:In code blocks, declare local functions with markup to serve as templating methods:

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

该代码呈现以下 HTML:The code renders the following HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

隐式转换Implicit transitions

代码块中的默认语言为 C#,不过,Razor 页面可以转换回 HTML:The default language in a code block is C#, but the Razor Page can transition back to HTML:

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

带分隔符的显式转换Explicit delimited transition

若要定义应呈现 HTML 的代码块子节,请使用 Razor <text> 标记将要呈现的字符括起来:To define a subsection of a code block that should render HTML, surround the characters for rendering with the Razor <text> tag:

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

使用此方法可呈现未被 HTML 标记括起来的 HTML。Use this approach to render HTML that isn't surrounded by an HTML tag. 如果没有 HTML 或 Razor 标记,会发生 Razor 运行时错误。Without an HTML or Razor tag, a Razor runtime error occurs.

<text> 标记可用于在呈现内容时控制空格:The <text> tag is useful to control whitespace when rendering content:

  • 仅呈现 <text> 标记之间的内容。Only the content between the <text> tag is rendered.
  • <text> 标记之前或之后的空格不会显示在 HTML 输出中。No whitespace before or after the <text> tag appears in the HTML output.

使用 @ 的显式行转换:Explicit Line Transition with @:

若要在代码块内以 HTML 的形式呈现整个行的其余内容,请使用 @: 语法:To render the rest of an entire line as HTML inside a code block, use the @: syntax:

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

如果代码中没有 @:,会生成 Razor 运行时错误。Without the @: in the code, a Razor runtime error is generated.

警告:Razor 文件中多余的 @ 字符可能会导致代码块中后面的语句发生编译器错误。Warning: Extra @ characters in a Razor file can cause compiler errors at statements later in the block. 这些编译器错误可能难以理解,因为实际错误发生在报告的错误之前。These compiler errors can be difficult to understand because the actual error occurs before the reported error. 将多个隐式/显式表达式合并到单个代码块以后,经常会发生此错误。This error is common after combining multiple implicit/explicit expressions into a single code block.

控制结构Control structures

控制结构是对代码块的扩展。Control structures are an extension of code blocks. 代码块的各个方面(转换为标记、内联 C#)同样适用于以下结构:All aspects of code blocks (transitioning to markup, inline C#) also apply to the following structures:

条件语句 @if、else if、else 和 @switchConditionals @if, else if, else, and @switch

@if 控制何时运行代码:@if controls when code runs:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

elseelse if 不需要 @ 符号:else and else if don't require the @ symbol:

@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 语句:The following markup shows how to use a switch statement:

@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 和 @do whileLooping @for, @foreach, @while, and @do while

可以使用循环控制语句呈现模板化 HTML。Templated HTML can be rendered with looping control statements. 若要呈现一组人员:To render a list of people:

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

支持以下循环语句:The following looping statements are supported:

@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);

复合语句 @usingCompound @using

在 C# 中,using 语句用于确保释放对象。In C#, a using statement is used to ensure an object is disposed. 在 Razor 中,可使用相同的机制来创建包含附加内容的 HTML 帮助程序。In Razor, the same mechanism is used to create HTML Helpers that contain additional content. 在下面的代码中,HTML 帮助程序使用 @using 语句呈现表单标记:In the following code, HTML Helpers render a form tag with the @using statement:

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

可以使用标记帮助程序执行作用域级别的操作。Scope-level actions can be performed with Tag Helpers.

@try、catch、finally@try, catch, finally

异常处理与 C# 类似:Exception handling is similar to 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 语句来保护关键节:Razor has the capability to protect critical sections with lock statements:

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

注释Comments

Razor 支持 C# 和 HTML 注释:Razor supports C# and HTML comments:

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

该代码呈现以下 HTML:The code renders the following HTML:

<!-- HTML comment -->

在呈现网页之前,服务器会删除 Razor 注释。Razor comments are removed by the server before the webpage is rendered. Razor 使用 @* *@ 来分隔注释。Razor uses @* *@ to delimit comments. 以下代码已被注释禁止,因此服务器不呈现任何标记:The following code is commented out, so the server doesn't render any markup:

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

指令Directives

Razor 指令由隐式表达式表示:@ 符号后跟保留关键字。Razor directives are represented by implicit expressions with reserved keywords following the @ symbol. 指令通常用于更改视图分析方式或启用不同的功能。A directive typically changes the way a view is parsed or enables different functionality.

通过了解 Razor 如何为视图生成代码,更易理解指令的工作原理。Understanding how Razor generates code for a view makes it easier to understand how directives work.

@{
    var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

该代码生成与下面类似的类:The code generates a class similar to the following:

public class _Views_Something_cshtml : RazorPage<dynamic>
{
    public override async Task ExecuteAsync()
    {
        var output = "Getting old ain't for wimps! - Anonymous";

        WriteLiteral("/r/n<div>Quote of the Day: ");
        Write(output);
        WriteLiteral("</div>");
    }
}

本文后面的检查为视图生成的 Razor C# 类部分说明了如何查看此生成的类。Later in this article, the section Inspect the Razor C# class generated for a view explains how to view this generated class.

@using

@using 指令用于向生成的视图添加 C# using 指令:The @using directive adds the C# using directive to the generated view:

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

@model

@model 指令指定传递到视图的模型类型:The @model directive specifies the type of the model passed to a view:

@model TypeNameOfModel

在使用个人用户帐户创建的 ASP.NET Core MVC 应用中,Views/Account/Login.cshtml 视图包含以下模型声明:In an ASP.NET Core MVC app created with individual user accounts, the Views/Account/Login.cshtml view contains the following model declaration:

@model LoginViewModel

生成的类继承自 RazorPage<dynamic>The class generated inherits from RazorPage<dynamic>:

public class _Views_Account_Login_cshtml : RazorPage<LoginViewModel>

Razor 公开了 Model 属性,用于访问传递到视图的模型:Razor exposes a Model property for accessing the model passed to the view:

<div>The Login Email: @Model.Email</div>

@model 指令指定此属性的类型。The @model directive specifies the type of this property. 该指令将 RazorPage<T> 中的 T 指定为生成的类,视图便派生自该类。The directive specifies the T in RazorPage<T> that the generated class that the view derives from. 如果未指定 @model 指令,则 Model 属性的类型为 dynamicIf the @model directive isn't specified, the Model property is of type dynamic. 模型的值会从控制器传递到视图。The value of the model is passed from the controller to the view. 有关详细信息,请参阅强类型模型和@模型关键字For more information, see Strongly typed models and the @model keyword.

@inherits

@inherits 指令对视图继承的类提供完全控制:The @inherits directive provides full control of the class the view inherits:

@inherits TypeNameOfClassToInheritFrom

下面的代码是一种自定义 Razor 页面类型:The following code is a custom Razor page type:

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 显示在视图中:The CustomText is displayed in a view:

@inherits CustomRazorPage<TModel>

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

该代码呈现以下 HTML:The code renders the following HTML:

<div>Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping a slop bucket on the street below.</div>

@model@inherits 可在同一视图中使用。@model and @inherits can be used in the same view. @inherits 可位于视图导入的 _ViewImports.cshtml 文件中:@inherits can be in a _ViewImports.cshtml file that the view imports:

@inherits CustomRazorPage<TModel>

下面的代码是一种强类型视图:The following code is an example of a strongly-typed view:

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>

如果在模型中传递“rick@contoso.com”,视图将生成以下 HTML 标记:If "rick@contoso.com" is passed in the model, the view generates the following HTML markup:

<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 页面将服务从服务容器注入到视图。The @inject directive enables the Razor Page to inject a service from the service container into a view. 有关详细信息,请参阅视图中的依赖关系注入For more information, see Dependency injection into views.

@functions

@functions 指令允许 Razor 页面将 C# 代码块添加到视图中:The @functions directive enables a Razor Page to add a C# code block to a view:

@functions { // C# Code }

例如:For example:

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

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

该代码生成以下 HTML 标记:The code generates the following HTML markup:

<div>From method: Hello</div>

以下代码是生成的 Razor C# 类:The following code is the generated Razor C# class:

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 方法有标记时,会用作模板化方法:@functions methods serve as templating methods when they have markup:

@{
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

@functions {
    private void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
}

该代码呈现以下 HTML:The code renders the following HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@attribute

@attribute 指令将给定的属性添加到生成的页或视图的类中。The @attribute directive adds the given attribute to the class of the generated page or view. 以下示例添加 [Authorize] 属性:The following example adds the [Authorize] attribute:

@attribute [Authorize]

警告

ASP.NET Core 3.0 Preview 6 发行版中存在一个已知问题,其中 @attribute 指令在 _Imports.razor 和 _ViewImports.cshtml 文件中无法正常工作 。In ASP.NET Core 3.0 Preview 6 release, there's a known issue where @attribute directives don't work in _Imports.razor and _ViewImports.cshtml files. 此问题将在 Preview 7 发行版中得到解决。This will be addressed in the Preview 7 release.

@namespace

@namespace 指令设置生成的页或视图的类的命名空间:The @namespace directive sets the namespace of the class of the generated page or view:

@namespace Your.Namespace.Here

如果页或视图使用 @namespace 指令导入 API,则原始文件的命名空间设置为相对于该命名空间。If a page or view imports API with an @namespace directive, the original file's namespace is set relative to that namespace.

如果 MyApp/Pages/_ViewImports.cshtml 包含 @namespace Hello.World,则导入 Hello.World 命名空间的页或视图的命名空间设置如下表所示 。If MyApp/Pages/_ViewImports.cshtml contains @namespace Hello.World, the namespace of pages or views that import the Hello.World namespace is set as shown in the following table.

页(或视图)Page (or view) 命名空间Namespace
MyApp/Pages/Index.cshtml MyApp/Pages/Index.cshtml Hello.World
MyApp/Pages/MorePages/Bar.cshtml MyApp/Pages/MorePages/Bar.cshtml Hello.World.MorePages

如果多个导入文件都具有 @namespace 指令,则使用目录链中最接近页或视图的文件。If multiple import files have the @namespace directive, the file closest to the page or view in the directory chain is used.

@section

@section 指令与布局结合使用,允许页或视图将内容呈现在 HTML 页的不同部分。The @section directive is used in conjunction with the layout to enable pages or views to render content in different parts of the HTML page. 有关详细信息,请参阅部分For more information, see Sections.

模板化 Razor 委托Templated Razor delegates

通过 Razor 模板,可使用以下格式定义 UI 代码片段:Razor templates allow you to define a UI snippet with the following format:

@<tag>...</tag>

下面的示例演示如何指定模板化 Razor 委托作为 Func<T,TResult>The following example illustrates how to specify a templated Razor delegate as a Func<T,TResult>. 为委托封装的方法的参数指定动态类型The dynamic type is specified for the parameter of the method that the delegate encapsulates. 对象类型指定为委托的返回值。An object type is specified as the return value of the delegate. 该模板与 Pet(具有 Name 属性)的 List<T> 一起使用。The template is used with a List<T> of Pet that has a Name property.

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 呈现该模板:The template is rendered with pets supplied by a foreach statement:

@foreach (var pet in pets)
{
    @petTemplate(pet)
}

呈现的输出:Rendered output:

<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 模板作为方法的参数。You can also supply an inline Razor template as an argument to a method. 如下示例中,Repeat 方法收到一个 Razor 模板。In the following example, the Repeat method receives a Razor template. 该方法使用模板生成 HTML 内容,其中包含列表中提供的重复项:The method uses the template to produce HTML content with repeats of items supplied from a list:

@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 方法以及:Using the list of pets from the prior example, the Repeat method is called with:

  • PetList<T>List<T> of Pet.
  • 每只宠物的重复次数。Number of times to repeat each pet.
  • 用于无序列表的列表项的内联模板。Inline template to use for the list items of an unordered list.
<ul>
    @Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

呈现的输出:Rendered output:

<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>

标记帮助程序Tag Helpers

标记帮助程序有三个相关指令。There are three directives that pertain to Tag Helpers.

指令Directive 函数Function
@addTagHelper@addTagHelper 向视图提供标记帮助程序。Makes Tag Helpers available to a view.
@removeTagHelper@removeTagHelper 从视图中删除以前添加的标记帮助程序。Removes Tag Helpers previously added from a view.
@tagHelperPrefix@tagHelperPrefix 指定标记前缀,以启用标记帮助程序支持并阐明标记帮助程序的用法。Specifies a tag prefix to enable Tag Helper support and to make Tag Helper usage explicit.

Razor 保留关键字Razor reserved keywords

Razor 关键字Razor keywords

  • page(需要 ASP.NET Core 2.0 及更高版本)page (Requires ASP.NET Core 2.0 and later)
  • namespacenamespace
  • functionsfunctions
  • inheritsinherits
  • modelmodel
  • sectionsection
  • helper(ASP.NET Core 当前不支持)helper (Not currently supported by ASP.NET Core)

Razor 关键字使用 @(Razor Keyword) 进行转义(例如,@(functions))。Razor keywords are escaped with @(Razor Keyword) (for example, @(functions)).

C# Razor 关键字C# Razor keywords

  • casecase
  • dodo
  • defaultdefault
  • forfor
  • foreachforeach
  • ifif
  • elseelse
  • locklock
  • switchswitch
  • trytry
  • catchcatch
  • finallyfinally
  • usingusing
  • whilewhile

C# Razor 关键字必须使用 @(@C# Razor Keyword) 进行双转义(例如,@(@case))。C# Razor keywords must be double-escaped with @(@C# Razor Keyword) (for example, @(@case)). 第一个 @ 对 Razor 分析器转义。The first @ escapes the Razor parser. 第二个 @ 对 C# 分析器转义。The second @ escapes the C# parser.

Razor 不使用的保留关键字Reserved keywords not used by Razor

  • classclass

检查为视图生成的 Razor C# 类Inspect the Razor C# class generated for a view

在 .NET Core SDK 2.1 或更高版本中,Razor SDK 负责编译 Razor 文件。With .NET Core SDK 2.1 or later, the Razor SDK handles compilation of Razor files. 生成项目时,Razor SDK 在项目根目录中生成 obj/<build_configuration>/<target_framework_moniker>/Razor 目录 。When building a project, the Razor SDK generates an obj/<build_configuration>/<target_framework_moniker>/Razor directory in the project root. Razor 目录中的目录结构反映项目的目录结构 。The directory structure within the Razor directory mirrors the project's directory structure.

在面向 .NET Core 2.1 的 ASP.NET Core 2.1 Razor Pages 项目中,请考虑以下目录结构:Consider the following directory structure in an ASP.NET Core 2.1 Razor Pages project targeting .NET Core 2.1:

  • Areas/ Areas/
    • Admin/ Admin/
      • Pages/ Pages/
        • Index.cshtml Index.cshtml
        • Index.cshtml.cs Index.cshtml.cs
  • Pages/ Pages/
    • Shared/ Shared/
      • _Layout.cshtml _Layout.cshtml
    • _ViewImports.cshtml _ViewImports.cshtml
    • _ViewStart.cshtml_ViewStart.cshtml
    • Index.cshtml Index.cshtml
    • Index.cshtml.cs Index.cshtml.cs

在 Debug 配置下生成项目将生成以下 obj 目录 :Building the project in Debug configuration yields the following obj directory:

  • obj/ obj/
    • Debug/ Debug/
      • netcoreapp2.1/ netcoreapp2.1/
        • Razor/ Razor/
          • Areas/ Areas/
            • Admin/ Admin/
              • Pages/ Pages/
                • Index.g.cshtml.cs Index.g.cshtml.cs
          • Pages/ Pages/
            • Shared/ Shared/
              • _Layout.g.cshtml.cs _Layout.g.cshtml.cs
            • _ViewImports.g.cshtml.cs _ViewImports.g.cshtml.cs
            • _ViewStart.g.cshtml.cs _ViewStart.g.cshtml.cs
            • Index.g.cshtml.cs Index.g.cshtml.cs

若要查看 Pages/Index.cshtml 的生成类,请打开 obj/Debug/netcoreapp2.1/Razor/Pages/Index.g.cshtml.cs 。To view the generated class for Pages/Index.cshtml, open obj/Debug/netcoreapp2.1/Razor/Pages/Index.g.cshtml.cs.

将下面的类添加到 ASP.NET Core MVC 项目:Add the following class to the ASP.NET Core MVC project:

using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;

public class CustomTemplateEngine : MvcRazorTemplateEngine
{
    public CustomTemplateEngine(RazorEngine engine, RazorProject project) 
        : base(engine, project)
    {
    }
        
    public override RazorCSharpDocument GenerateCode(RazorCodeDocument codeDocument)
    {
        var csharpDocument = base.GenerateCode(codeDocument);
        var generatedCode = csharpDocument.GeneratedCode;

        // Look at generatedCode

        return csharpDocument;
    }
}

Startup.ConfigureServices 中,使用 CustomTemplateEngine 类替代 MVC 添加的 RazorTemplateEngineIn Startup.ConfigureServices, override the RazorTemplateEngine added by MVC with the CustomTemplateEngine class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<RazorTemplateEngine, CustomTemplateEngine>();
}

CustomTemplateEnginereturn csharpDocument; 语句上设置断点。Set a breakpoint on the return csharpDocument; statement of CustomTemplateEngine. 当程序执行在断点处停止时,查看 generatedCode 的值。When program execution stops at the breakpoint, view the value of generatedCode.

generatedCode 的文本可视化工具视图

视图查找和区分大小写View lookups and case sensitivity

Razor 视图引擎为视图执行区分大小写的查找。The Razor view engine performs case-sensitive lookups for views. 但是,实际查找取决于基础文件系统:However, the actual lookup is determined by the underlying file system:

  • 基于文件的源:File based source:
    • 在使用不区分大小写的文件系统的操作系统(例如,Windows)上,物理文件提供程序查找不区分大小写。On operating systems with case insensitive file systems (for example, Windows), physical file provider lookups are case insensitive. 例如,return View("Test") 可匹配 /Views/Home/Test.cshtml/Views/home/test.cshtml 以及任何其他大小写变体。For example, return View("Test") results in matches for /Views/Home/Test.cshtml, /Views/home/test.cshtml, and any other casing variant.
    • 在区分大小写的文件系统(例如,Linux、OSX 以及使用 EmbeddedFileProvider 构建的文件系统)上,查找区分大小写。On case-sensitive file systems (for example, Linux, OSX, and with EmbeddedFileProvider), lookups are case-sensitive. 例如,return View("Test") 专门匹配 /Views/Home/Test.cshtmlFor example, return View("Test") specifically matches /Views/Home/Test.cshtml.
  • 预编译视图:在 ASP.NET Core 2.0 及更高版本中,预编译视图查找在所有操作系统上均不区分大小写。Precompiled views: With ASP.NET Core 2.0 and later, looking up precompiled views is case insensitive on all operating systems. 该行为与 Windows 上物理文件提供程序的行为相同。The behavior is identical to physical file provider's behavior on Windows. 如果两个预编译视图仅大小写不同,则查找的结果具有不确定性。If two precompiled views differ only in case, the result of lookup is non-deterministic.

建议开发人员将文件和目录名称的大小写与以下项的大小写匹配:Developers are encouraged to match the casing of file and directory names to the casing of:

  • 区域、控制器和操作名称。Area, controller, and action names.
  • Razor 页面。Razor Pages.

匹配大小写可确保无论使用哪种基础文件系统,部署都能找到其视图。Matching case ensures the deployments find their views regardless of the underlying file system.