zoukankan      html  css  js  c++  java
  • ASP.NET Core 中文文档 第四章 MVC(3.2)Razor 语法参考

    原文:Razor Syntax Reference
    作者:Taylor MullenRick Anderson
    翻译:刘怡(AlexLEWIS)
    校对:何镇汐

    什么是 Razor?

    Razor 是一种基于服务器端代码的可以转换为网页的标记语法。Razor 语法包括 Razor 标记、C# 和 HTML 组成。包含 Razor 的文件通常后缀名为 .cshtml

    渲染 HTML

    Razor 的默认语言是 HTML。从 Razor 渲染为 HTML 和直接一个 HTML 文件没啥区别,这种 Razor 文件包含下面的标记:

    <p>Hello World</p>
    

    服务器最后渲染出的页面也是 <p>Hello World</p>,没有任何改变。

    Razor 语法

    Razor 支持 C# 并通过使用 @ 符号从 HTML 切换到 C#。Razor 运算 C# 表达式并将之渲染为 HTML 输出。Razor 能通过 Razor 指定的标记从 HTML 切换到 C#。当 @ 符号后面紧跟一个 Razor 保留字 ,则将切换为 Razor 特定标记,不然的话切换到普通的 C#。

    HTML 如果需要包含 @ 符号的话需要使用两个 @@ 符号来进行转义,比如:

    <p>@@Username</p>
    

    这样将渲染成下面的 HTML:

     <p>@Username</p>
    

    这样就不会因为在 HTML 特性或内容中包含邮件地址而误将 @ 处理为转换字符(进而切换到 Razor 指定标记或 C# 模式)。
    <a href="mailto:Support@contoso.com">Support@contoso.com</a>

    隐式 Razor 表达式

    隐式 Razor 表达式起于 @ 符号,后面紧跟 C# 代码,比如:

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

    除 C# 关键字 await 以外的隐式表达式都不能包含空格。比如你可以在 C# 语句中混进一些空格,只要 C# 语句的结尾明确:

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

    显式 Razor 表达式

    显式 Razor 表达式包含一个带一对括号的 @ 符号,比如在页面上渲染上周的时间:

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

    任何在 @() 内的内容都会被运算并渲染输出。
    隐式表达式通常不能包含空格,比如下面这段代码,上周的时间并不能通过减去当前时间来获得:

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

    这将会被渲染为:

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

    Expression 编码

    C# 表达式计算后的字符串是 HTML 编码的。C# 表达式的计算结果为 IHtmlContent,将直接通过 IHtmlContent.WriteTo 渲染到页面。不会计算为 IHtmlContent 的 C# 表达式将会转换为字符串(通过 ToString)并在渲染前编码。比方说下面这段 Razor 标记:

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

    将渲染为这段 HTML:

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

    而浏览器将显示为:

    <span>Hello World</span>

    HtmlHelper Raw 的输出不会被编码但会被渲染为 HTML 标记。

    警告
    为未经认可的用户输入使用 HtmlHelper.Raw 是存在安全风险的。用户输入可能会包含恶意的 JavaScript 代码或其他攻击。为用户输入的信息进行过滤和清理是非常困难的,所以尽量避免为用户输入使用 HtmlHelper.Raw

    下面这段 Razor 标记:

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

    将渲染为:

    <span>Hello World</span>
    

    Razor 代码块

    Razor 代码块起于 @ 并用 {} 包围起来。不像表达式,代码块内的 C# 代码不会被渲染到页面中。Razor 页面中的代码块和表达式将共享同一个作用域,并按顺序定义(也就是说,之前在代码块中声明的对象可以在之后的代码块与表达式中使用)。

    @{
        var output = "Hello World";
    }
    
    <p>The rendered result: @output</p>
    

    将渲染为:

    <p>The rendered result: Hello World</p>
    

    隐式转换

    代码块的默认语言是 C#,但你可以随时切换到 HTML。代码块内的 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 页面会在运行时出错。

    @: 符号显式行转换

    为了将 HTML 内嵌到代码块中(以便能渲染出来),可以使用 @: 语法:

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

    如果上面代码不使用 @: ,你的 Razor 页面会在运行时出错。

    控制结构

    控制结构(controller structures)是代码块表达式。所有类型的代码块(包括过渡标记、内联式C#)都适用以下结构:

    @ifelse ifelse@switch 条件

    @if 满足指定条件时,@if 系列关键词将获得控制权并运行 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 was not large and is odd.</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 was not 1 or 1337.</p>
            break;
    }
    

    @for@foreach@while@do while 循环

    你可以使用循环控制语句渲染出经过排版的 HTML,比如人名表:

    @{
        var people = new Person[]
        {
              new Person("John", 33),
              new Person("Doe", 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 helpers 。比如我们可以利用 HTML helpers ,通过 @using 语句渲染 form 标签:

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

    你也可以在作用级别上执行一些类似上面这样的带 Tag Helpers 的操作。

    @trycatchfinally

    异常处理和 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 comment -->
    

    Razor 注释将在页面渲染之前被服务器移除。Razor 使用 @* *@ 来界定注释。下面这段代码就被注释掉了,因此服务器不会渲染出任何标记:

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

    指令

    Razor 指令表现为「@ 符号 + 保留关键字」的隐式表达式。指令通常能改变页面的解析或为 Razor 页面启用不同的功能。
    理解 Razor 如何为视图生成代码后,就能轻松理解指令是如何工作的。Razor 页面用于创建 C# 文件,比如这样一个 Razor 页面:

    @{
        var output = "Hello World";
    }
    
    <div>Output: @output</div>
    

    将生成一个类似下面这样的类:

    public class _Views_Something_cshtml : RazorPage<dynamic>
    {
        public override async Task ExecuteAsync()
        {
            var output = "Hello World";
    
            WriteLiteral("/r/n<div>Output: ");
            Write(output);
            WriteLiteral("</div>");
        }
    }
    

    查看生成视图的 Razor C# 类解释了如何查看这段自动生成的类。

    @using

    @using 指令将为 razor 页面增加 C# 的 using 指令。

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

    @model

    @model 指令让你可以为传入 Razor 页面的模型指定类型,其语法为:

    @model TypeNameOfModel
    

    比方说,如果你创建了一个带身份验证的 ASP.NET Core MVC 应用,你可以在 Views/Account/Login.cshtml Razor 视图文件中看到包含如下这段模型声明:

    @model LoginViewModel
    

    指令 样例类中,自动生成的类从 RazorPage<dynamic> 继承。通过添加 @model,你可以控制继承什么,比如:

    @model LoginViewModel
    

    将生成下面这个类

    public class _Views_Account_Login_cshtml : RazorPage<LoginViewModel>
    

    Razor 页面将暴露一个 Model 属性给传入页面的模型访问。

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

    @model 指令能为这个属性指定类型(通过为自动生成的类 RazorPage<T> 中的 T 指定类型)。如果你没有指定 @model 指令,那么 Model 属性将使用类型 dynamic 。模型的值将从控制器传入视图。更多请查阅 Strongly typed models and the @model keyword

    @inherits

    @inherits 指令让你具有 Razor 页面所继承类的完整控制权:

    @inherits TypeNameOfClassToInheritFrom
    

    例如让我们来看下面这个自定义的 Razor 页面类型:

    using Microsoft.AspNetCore.Mvc.Razor;
    
    public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
    {
        public string CustomText { get; } = "Hello World.";
    }
    

    随后 Razor 将生成 <div>Custom text: Hello World</div>

    @inherits CustomRazorPage<TModel>
    
    <div>Custom text: @CustomText</div>
    

    你不能在同一个页面中同时使用 @model@inherits。你可以在 _ViewImports.cshtml 文件中使用 @inherits 指令,然后在其他 Razor 页面中导入。举例来说,如果你的 Razor 视图导入了下面这个 _ViewImports.cshtml 文件:

    @inherits CustomRazorPage<TModel>
    

    那么在下面这个强类型 Razor 文件

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

    将生成这么一段 HTML 标记:

    <div>The Login Email: Rick@contoso.com</div>
    <div>Custom text: Hello World</div>
    

    此时模型中被传入了「Rick@contoso.com」。

    更多信息请查看 布局视图

    @inject

    @inject 指令可让你在 Razor 页面中从 服务容器 注入服务,更多请查看 See Injecting Services Into Views

    @functions

    @functions 指令让你能在 Razor 页面中添加函数级别的内容,其语法为:

    @functions { // C# Code }
    

    例如:

    @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("
    <div>From method: ");
            Write(GetHello());
            WriteLiteral("</div>
    ");
        }
    #pragma warning restore 1998
    

    @section

    @section 指令通常与 布局页 一起使用,这样可以使视图所渲染的 HTML 页面能具有不同的内容。更多请查看 Sections

    TagHelpers

    下列 Tag Helpers 指令的详细信息可以点击链接查看。

    Razor 保留关键字

    Razor 关键字

    • functions
    • inherits
    • model
    • section
    • helper (ASP.NET Core 不支持)

    Razor 关键字可以转义,形如 @(Razor Keyword) ,举一个例子:@(functions) 。上面是完整举例。

    C# Razor 关键字

    • case
    • do
    • default
    • for
    • foreach
    • if
    • lock
    • switch
    • try
    • using
    • while

    C# Razor 关键字需要使用两个转义符号,形如 @(@C# Razor Keyword),举一个实际例子:@(@case) 。第一个 @ 转义符用于 Razor 解析,第二个 @ 转义符用于 C# 解析。上面是完整举例。

    Razor 未使用的保留关键字

    • namespace
    • class

    下列是所有 Razor 保留字的转义:

    @{
        // Razor keywords.
    
        var @functions = "functions";
        var @inherits = "inherits";
        var @model = "model";
        var @section = "section";
        var @helper = "helper";         // Not supported by ASP.NET Core.
    
        // C# Razor keywords.
    
        var @case = "case";
        var @do = "do";
        var @default = "default";
        var @for = "for";
        var @foreach = "foreach";
        var @if = "if";
        var @lock = "lock";
        var @switch = "switch";
        var @try = "try";
        var @using = "using";
        var @while = "while";
    
        // Reserved keywords not used.
    
        var @namespace = "namespace";
        var @class = "class";
    }
    
    <p>Razor keywords.</p>
    <div>@(functions)</div>
    <div>@(inherits)</div>
    <div>@(model)</div>
    <div>@(section)</div>
    <div>@(helper)</div>
    
    <p>C# Razor keywords.</p>
    <div>@(@case)</div>
    <div>@(@do)</div>
    <div>@(@default)</div>
    <div>@(@for)</div>
    <div>@(@foreach)</div>
    <div>@(@if)</div>
    <div>@(@lock)</div>
    <div>@(@switch)</div>
    <div>@(@try)</div>
    <div>@(@using)</div>
    <div>@(@while)</div>
    
    <p>Reserved keywords not used</p>
    <div>@(@namespace)</div>
    <div>@(@class)</div>
    

    查看生成视图的 Razor C# 类

    在 ASP.NET Core MVC 项目中增加下面这个类:

    using Microsoft.AspNetCore.Mvc.ApplicationParts;
    using Microsoft.AspNetCore.Mvc.Razor;
    using Microsoft.AspNetCore.Mvc.Razor.Compilation;
    using Microsoft.AspNetCore.Mvc.Razor.Internal;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    public class CustomCompilationService : DefaultRoslynCompilationService, ICompilationService
    {
        public CustomCompilationService(ApplicationPartManager partManager, 
            IOptions<RazorViewEngineOptions> optionsAccessor, 
            IRazorViewEngineFileProviderAccessor fileProviderAccessor, 
            ILoggerFactory loggerFactory) 
            : base(partManager, optionsAccessor, fileProviderAccessor, loggerFactory)
        {
        }
    
        CompilationResult ICompilationService.Compile(RelativeFileInfo fileInfo, 
            string compilationContent)
        {
            return base.Compile(fileInfo, compilationContent);
        }
    }
    

    通过为 MVC 加上上面这个类来覆盖 ICompilationService

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

    Compile 方法的 CustomCompilationService 上、在视图compilationContent 上设断点。

    返回目录

  • 相关阅读:
    web前端之Javascript的输出
    python编码问题
    python面试题1
    机器学习三剑客补充
    JavaScript设计模式与开发实践 组合模式
    JavaScript设计模式与开发实践 命令模式
    JavaScript设计模式与开发实践 发布—订阅模式
    JavaScript设计模式与开发实践 迭代器模式
    JavaScript设计模式与开发实践 代理模式
    JavaScript设计模式与开发实践 策略模式
  • 原文地址:https://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-4_3_2-razor.html
Copyright © 2011-2022 走看看