ASP.NET Core 中的标记帮助程序

作者:Rick Anderson

什么是标记帮助程序

标记帮助程序使服务器端代码能够参与创建和呈现文件中的 Razor HTML 元素。 例如,内置 ImageTagHelper 可以向映像名称追加版本号。 每当映像发生更改时,服务器都会为映像生成新的唯一版本,因此可以保证客户端获取当前映像(而不是过时的缓存映像)。 有许多内置标记帮助程序用于常见任务(例如创建表单、链接、加载资产等),甚至在公共 GitHub 存储库中和 NuGet 包中也更多可用。 标记帮助程序以 C# 编写,它们基于元素名称、属性名称或父标记面向 HTML 元素。 例如,内置的LabelTagHelper在应用<label>属性时,可以针对 HTML LabelTagHelper元素。 如果熟悉 HTML 帮助程序,标记帮助程序可减少视图中 HTML 和 C# Razor 之间的显式转换。 在许多情况下,HTML 帮助程序为特定的标记帮助程序提供了替代方法,但必须认识到标记帮助程序不会替换 HTML 帮助程序,并且每个 HTML 帮助程序没有标记帮助程序。 与 HTML 帮助程序相比,标记帮助程序 更详细地解释了差异。

组件不支持 Razor 标签帮助器。 有关详细信息,请参阅 ASP.NET Core Razor 组件

标记帮助程序提供的内容

HTML 友好开发体验

在大多数情况下, Razor 使用标记帮助器的标记看起来类似于标准 HTML。 与 HTML/CSS/JavaScript 交互的前端设计器可以在不学习 C# Razor 语法的情况下进行编辑Razor。

用于创建 HTML 和 Razor 标记的丰富 IntelliSense 环境

这与前一种方法,即在Razor视图中使用服务器端的HTML助手来创建标记,形成鲜明对比。 与 HTML 帮助程序相比,标记帮助程序 更详细地解释了差异。 对标记帮助器的 IntelliSense 支持 说明了 IntelliSense 环境。 即使是使用 Razor C# 语法的开发人员,使用标记帮助程序比编写 C# Razor 标记更有效率。

一种使用仅在服务器上提供的信息提高工作效率并能够生成更可靠、更可靠且可维护的代码的方法

例如,过去更新图像的惯例是在更改图像时更改图像的名称。 出于性能原因,应主动缓存映像,除非更改映像的名称,否则客户端可能会收到过时的副本。 从历史上看,在编辑图像后,必须更改名称,并且需要更新对 Web 应用中图像的每个引用。 这不仅非常费力,而且很容易出错(你可能会错过引用,意外输入错误的字符串等)。内置的ImageTagHelper 可以自动完成这项工作。 可以将 ImageTagHelper 版本号追加到映像名称,因此每当映像发生更改时,服务器都会自动生成映像的新唯一版本。 保证客户能够获取当前图像。 使用ImageTagHelper 后,这种稳健性和人工节省基本上是免费的。

大多数内置标记帮助程序面向标准 HTML 元素,并为该元素提供服务器端属性。 例如,<input> 元素用于 Views/Account 文件夹中的许多视图,并包含 asp-for 属性。 此属性将指定模型属性的名称提取到呈现的 HTML 中。 请考虑使用以下 Razor 模型的视图:

public class Movie
{
    public int ID { get; set; }
    public string Title { get; set; }
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; }
}

以下 Razor 标记:

<label asp-for="Movie.Title"></label>

则会生成以下 HTML:

<label for="Movie_Title">Title</label>

asp-for特性通过For属性在LabelTagHelper中提供。 有关详细信息,请参阅 作者标记帮助程序

管理标记帮助程序范围

标记帮助程序的范围由@addTagHelper@removeTagHelper和“!”选择退出字符的组合来控制。

@addTagHelper 使标记助手可用

如果创建名为 AuthoringTagHelpers 的新 ASP.NET Core Web 应用,则会将以下 Views/_ViewImports.cshtml 文件添加到项目中:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, AuthoringTagHelpers

@addTagHelper 指令使 Tag Helper 可供视图使用。 在这种情况下,视图文件 Pages/_ViewImports.cshtml默认由 Pages 文件夹和子文件夹中的所有文件继承;使标记帮助程序可用。 上述代码使用通配符语法(“*”)来指定程序集 (Microsoft.AspNetCore.Mvc.TagHelpers) 中的所有标记帮助程序,这些将会可用于 Views 目录或其子目录中的每个视图文件。 指定要加载的标记帮助器的第一个参数位于@addTagHelper之后(我们使用“*”表示所有标记帮助器),第二个参数“Microsoft.AspNetCore.Mvc.TagHelpers”指定包含这些标记帮助器的程序集。 Microsoft.AspNetCore.Mvc.TagHelpers 是内置 ASP.NET 核心标记帮助器的程序集。

若要公开此项目中的所有标记帮助程序(这将创建名为 AuthoringTagHelpers 的程序集),请使用以下内容:

@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, AuthoringTagHelpers

如果项目中包含具有默认命名空间(EmailTagHelper)的 AuthoringTagHelpers.TagHelpers.EmailTagHelper,则可以提供标记帮助程序的完整限定名称(FQN):

@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper AuthoringTagHelpers.TagHelpers.EmailTagHelper, AuthoringTagHelpers

若要使用 FQN 将标记帮助程序添加到视图中,首先添加 FQN(AuthoringTagHelpers.TagHelpers.EmailTagHelper),然后添加程序集名称(AuthoringTagHelpers)。 大多数开发人员更喜欢使用“*”通配符语法。 通配符语法允许在 FQN 中插入通配符“*”作为后缀。 例如,以下任何指令都将引入 EmailTagHelper

@addTagHelper AuthoringTagHelpers.TagHelpers.E*, AuthoringTagHelpers
@addTagHelper AuthoringTagHelpers.TagHelpers.Email*, AuthoringTagHelpers

如前所述,将 @addTagHelper 指令添加到 Views/_ViewImports.cshtml 文件会使标记帮助程序可用于 Views 目录和子目录中的所有视图文件。 如果要选择仅在特定视图中公开标签辅助工具,可以在这些视图文件中使用 @addTagHelper 指令。

@removeTagHelper 删除标记帮助程序

@removeTagHelper 具有与 @addTagHelper 相同的两个参数,并移除一个此前添加的标记帮助程序。 例如,@removeTagHelper 应用于特定视图时,将从视图中移除指定的标签助手。 在文件中使用@removeTagHelper会从Views/Folder/_ViewImports.cshtml的所有视图中删除指定的标记帮助程序。

使用 _ViewImports.cshtml 文件控制标记帮助器的范围

可以将 a _ViewImports.cshtml 添加到任何视图文件夹,并且视图引擎将应用该文件和 Views/_ViewImports.cshtml 文件中的指令。 如果为Views/Home/_ViewImports.cshtml视图添加了空Home文件,因为该_ViewImports.cshtml文件是累加的,则不会有任何变化。 添加到@addTagHelper文件中的任何Views/Home/_ViewImports.cshtml指令(不在默认Views/_ViewImports.cshtml文件中)将仅在Home文件夹内的视图中公开这些标记帮助程序。

取消选择单个的元素

可以在元素级别使用标记帮手的取消字符(“!”)来禁用标记帮手。 例如,在使用标记助手的取消字符Email中禁用<span>验证:

<!span asp-validation-for="Email" class="text-danger"></!span>

必须在起始和结束标签中应用 Tag Helper 退出字符。 (将选择退出字符添加到开始标记时,Visual Studio 编辑器会自动将选择退出字符添加到结束标记)。 添加选择退出字符后,元素和标记辅助器属性不再以独特的字体显示。

使用 @tagHelperPrefix 来明确标记帮助器的使用

@tagHelperPrefix 指令允许指定标记前缀字符串以启用标记帮助程序支持,并使标记帮助程序用法显式。 例如,可以将以下标记添加到 Views/_ViewImports.cshtml 该文件:

@tagHelperPrefix th:

在下面的代码图中,标记帮助程序前缀设置为 th:,因此,只有使用前缀 th: 的元素支持标记帮助程序(标记帮助程序启用的元素具有独特的字体)。 具有标记帮助程序前缀并启用标记帮助程序的元素有<label><input>,而<span>元素则没有。

Razor 使用前缀设置为“th:”的标签帮助程序的标记和输入元素名称

应用于 @addTagHelper 的同一层次结构规则也适用于 @tagHelperPrefix

自我关闭标记帮助程序

许多标签帮助器不能用作自闭合标签。 某些 Tag Helper 被设计为自闭合标签。 使用不支持自闭合的标签帮助程序会抑制渲染的输出。 自关闭 Tag Helper 会导致呈现输出中的自关闭标签。 有关详细信息,请参阅创作标记帮助程序中的此说明

标记帮助程序中的 C# 属性/声明

Tag Helper 不允许在元素的属性或标记声明区域中使用 C#。 例如,以下代码无效:

<input asp-for="LastName"  
       @(Model?.LicenseId == null ? "disabled" : string.Empty) />

上述代码可以编写为:

<input asp-for="LastName" 
       disabled="@(Model?.LicenseId == null)" />

通常, @ 运算符将表达式的文本表示形式插入到呈现的 HTML 标记中。 但是,当表达式的计算结果为逻辑 false时,框架会删除该属性。 在前面的示例中,如果disabledtrueModel,则 LicenseId 属性将设置为 null

标记助手初始化

虽然属性可用于配置标签辅助程序的各个实例,但 ITagHelperInitializer<TTagHelper> 可用于配置特定类型的所有标签辅助程序实例。 考虑以下示例,其中一个标记帮助程序初始化器为应用中的所有asp-append-version实例配置AppendVersion属性或ScriptTagHelper属性:

public class AppendVersionTagHelperInitializer : ITagHelperInitializer<ScriptTagHelper>
{
    public void Initialize(ScriptTagHelper helper, ViewContext context)
    {
        helper.AppendVersion = true;
    }
}

要使用初始化器,请在应用程序启动时注册它来进行配置。

builder.Services.AddSingleton
    <ITagHelperInitializer<ScriptTagHelper>, AppendVersionTagHelperInitializer>();

在 wwwroot 之外自动生成版本的 Tag Helper

有关标记帮助程序为外部 wwwroot静态文件生成版本,请参阅 从多个位置提供文件

对标记帮助器的 IntelliSense 支持

请考虑编写 HTML <label> 元素。 一旦在 Visual Studio 编辑器中输入 <l ,IntelliSense 就会显示匹配的元素:

在键盘上键入“l”后,IntelliSense 会建议选择“label”的可能标记名称列表。

你不仅获得 HTML 帮助,而且还获得图标(图标下带有“<>@”符号)。

其下带有“@”的“<>@”符号。

该图标将元素标识为标签助手的目标元素。 纯 HTML 元素(如 ) fieldset显示“<>”图标。

纯 HTML <label> 标记以棕色字体显示 HTML 标记(默认为 Visual Studio 颜色主题),属性以红色显示,属性值为蓝色。

示例“label”HTML 标记

输入 <label后,IntelliSense 会列出可用的 HTML/CSS 属性及 Tag Helper 的目标属性:

用户已键入左括号和 HTML 元素名称“label”。IntelliSense 提供可能的属性列表(未预先选择)。

IntelliSense 语句完成允许输入 Tab 键以使用所选值完成语句:

用户键入了左括号和 HTML 元素名称“label”,并开始输入属性名称(“as”)。此时,IntelliSense 显示了一个建议对话框,其中“asp-for”已被选中。

输入 Tag Helper 属性后,标记和属性的字体就会改变。 使用默认的 Visual Studio“Blue”或“浅色”颜色主题,字体为粗体紫色。 如果使用“深色”主题,字体为粗体青色。 本文档中的图像是使用默认主题拍摄的。

用户选择了“asp-for”,现在为粗体紫色,因为用户未使用深色主题。

可以在双引号(“”)内输入 Visual Studio CompleteWord 快捷键(Ctrl + 空格键 为默认设置),然后您就会进入 C# 环境,就像在 C# 类中一样。 IntelliSense 显示页面模型上的所有方法和属性。 方法和属性可用,因为属性类型为 ModelExpression. 在下图中,我正在编辑 Register 视图,因此 RegisterViewModel 可用。

用户在“asp-for”属性的值中键入“e”。IntelliSense 建议在选中“电子邮件”的情况下完成。

IntelliSense 列出了页面上模型可用的属性和方法。 丰富的 IntelliSense 环境可帮助你选择 CSS 类:

用户键入“cl”,将属性添加到“input”元素。IntelliSense 提供了一系列完成建议,其中选择了“class”。

用户键入“co”作为“input”元素的“class”属性的值。IntelliSense 提供了完成建议列表,其中选择了“col”。

与 HTML 帮助程序相比,标记帮助程序

标记协助程序附着在 Razor 视图中的 HTML 元素上,而 HTML 协助程序则作为方法调用,与 Razor 视图中的 HTML 互相交织进行。 请考虑以下 Razor 标记,该标记使用 CSS 类“caption”创建 HTML 标签:

@Html.Label("FirstName", "First Name:", new {@class="caption"})

at (@) 符号告知 Razor 这是代码的开头。 接下来的两个参数(“FirstName”和“First Name:”)是字符串,因此 IntelliSense 无法提供帮助。 最后一个参数:

new {@class="caption"}

用于表示属性的匿名对象。 由于 class 是 C# 中的保留关键字,因此使用 @ 符号强制 C# 解释 @class= 为符号(属性名称)。 对于前端设计师(熟悉 HTML/CSS/JavaScript 和其他客户端技术但不熟悉 C# 和 Razor),大多数语句对他来说都是陌生的。 在没有 IntelliSense 帮助的情况下,必须写完整行。

使用 LabelTagHelper时,可以编写相同的标记:

<label class="caption" asp-for="FirstName"></label>

使用标记帮助程序版本后,只要在 Visual Studio 编辑器中输入 <l ,IntelliSense 就会显示匹配的元素:

用户在键盘上键入“l”。IntelliSense 建议 HTML 元素完成,其中选择了“label”。

IntelliSense 帮助你完成整行代码的编写。

下面的代码图显示了 Visual Studio 随附的 ASP.NET 4.5.x MVC 模板生成的视图的 Views/Account/Register.cshtmlRazor 表单部分。

Razor ASP.NET 4.5 MVC 项目模板中“注册 Razor ”视图的表单部分标记

Visual Studio 编辑器显示具有灰色背景的 C# 代码。 例如, AntiForgeryToken HTML 帮助程序:

@Html.AntiForgeryToken()

以灰色背景显示。 寄存器视图中的大多数标记都是 C# 。 将这与使用标记帮助程序等效的方法进行比较:

Razor 使用标记帮助程序的标记,用于 ASP.NET Core 项目模板的“Register Razor”视图的表单部分

与 HTML 帮助程序方法相比,标记更简洁、更易于阅读、编辑和维护。 C# 代码减少到服务器需要了解的最小值。 Visual Studio 编辑器以独特的字体显示由标签助手定位的标记。

请考虑 电子邮件 组:

<div class="form-group">
    <label asp-for="Email" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="Email" class="form-control" />
        <span asp-validation-for="Email" class="text-danger"></span>
    </div>
</div>

每个“asp-”属性的值为“Email”,但“Email”不是字符串。 在此上下文中,“Email”是用于RegisterViewModel的C#模型表达式属性。

Visual Studio 编辑器可帮助你在标签帮助程序方法的注册表单中编写 所有 标记,而对于 HTML 帮助程序方法中的大多数代码,Visual Studio 不提供任何帮助。 对标记帮助程序的 IntelliSense 支持 详细介绍了在 Visual Studio 编辑器中如何使用标记帮助程序。

标记帮助程序与 Web 服务器控件相比

  • Tag Helpers 不拥有关联的元素,它们只是参与元素和内容的呈现。 ASP.NET Web 服务器控件在页面上声明和调用。

  • ASP.NET Web 服务器控件具有一个难以开发和调试的不简单生命周期。

  • Web 服务器控件允许使用客户端控件向客户端 DOM 元素添加功能。 标记帮助程序没有 DOM。

  • Web 服务器控件包括自动浏览器检测。 标记帮助程序没有关于浏览器的任何知识。

  • 多个标记帮助程序可以处理同一元素(请参阅 避免标记帮助程序冲突),而通常无法编写 Web 服务器控件。

  • 标记帮助程序可以修改其作用域为的 HTML 元素的标记和内容,但不直接修改页面上的任何其他元素。 Web 服务器控件具有较少具体的范围,可以执行影响页面其他部分的操作;可能会导致意外的副作用。

  • Web 服务器控件使用类型转换器将字符串转换为对象。 借助标记帮助程序,可以在 C# 中本机工作,因此无需执行类型转换。

  • Web 服务器控件用于 System.ComponentModel 实现组件和控件的运行时和设计时行为。 System.ComponentModel 包括用于实现属性和类型转换器、绑定到数据源和许可组件的基类和接口。 与通常派生自 TagHelper的标记帮助程序相比, TagHelper 基类只公开两种方法, Process 以及 ProcessAsync

自定义Tag Helper元素的字体

可以在工具>选项>环境>字体和颜色中自定义字体和颜色:

Visual Studio 中的“选项”对话框

内置 ASP.NET Core 标签帮助程序

锚点

缓存

元件

分布式缓存

环境

表单

表单操作

图像

输入

标签

链接

部分

保留组件状态

脚本

Select

Textarea

验证消息

验证摘要

其他资源