作者 :Scott Addie 和 Fiyaz Bin Hasan
标记帮助程序组件是一个标记帮助程序,可用于从服务器端代码有条件地修改或添加 HTML 元素。 此功能在 ASP.NET Core 2.0 或更高版本中可用。
ASP.NET Core 包括两个内置的标记帮助程序组件: head 和 body。 它们位于命名空间中 Microsoft.AspNetCore.Mvc.Razor.TagHelpers ,可在 MVC 和 Razor Pages 中使用。 标记帮助程序组件不需要在_ViewImports.cshtml中注册到应用。
用例
常见的标记帮助器组件用例包括两个:
以下部分介绍了这些用例。
注入 HTML 头元素
在 HTML <head> 元素中,CSS 文件通常与 HTML <link> 元素一起导入。 以下代码使用<link>标记帮助程序组件将<head>元素注入head元素。
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace RazorPagesSample.TagHelpers
{
public class AddressStyleTagHelperComponent : TagHelperComponent
{
private readonly string _style =
@"<link rel=""stylesheet"" href=""/css/address.css"" />";
public override int Order => 1;
public override Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "head",
StringComparison.OrdinalIgnoreCase))
{
output.PostContent.AppendHtml(_style);
}
return Task.CompletedTask;
}
}
}
在前面的代码中:
-
AddressStyleTagHelperComponent可实现 TagHelperComponent。 抽象:- 允许使用TagHelperContext初始化类。
- 允许使用标记帮助程序组件功能在 HTML 文档中添加或修改元素。
- 该 Order 属性定义呈现组件的顺序。
Order在应用中有多个标记助手组件的用法时是必需的。 -
ProcessAsync 将执行上下文的 TagName 属性值与
head进行比较。 如果比较的计算结果为 true,则字段的内容_style将注入到 HTML<head>元素中。
注入 HTML 正文元素
body标记帮助程序组件可以将<script>元素注入<body>元素。 以下代码演示了此技术:
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace RazorPagesSample.TagHelpers
{
public class AddressScriptTagHelperComponent : TagHelperComponent
{
public override int Order => 2;
public override async Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "body",
StringComparison.OrdinalIgnoreCase))
{
var script = await File.ReadAllTextAsync(
"TagHelpers/Templates/AddressToolTipScript.html");
output.PostContent.AppendHtml(script);
}
}
}
}
单独的 HTML 文件用于存储 <script> 元素。 HTML 文件使代码更简洁且更易于维护。 前面的代码读取 TagHelpers/Templates/AddressToolTipScript.html 的内容,并将其与标记助手的输出相结合。 该文件 AddressToolTipScript.html 包括以下标记:
<script>
$("address[printable]").hover(function() {
$(this).attr({
"data-toggle": "tooltip",
"data-placement": "right",
"title": "Home of Microsoft!"
});
});
</script>
前面的代码将 Bootstrap 工具提示小组件绑定到包含<address>属性的任何printable元素。 当鼠标指针悬停在元素上时,效果可见。
注册组件
必须将标签助手组件添加到应用程序的标签助手组件集合中。 有三种方法可以添加到集合中:
通过服务容器注册
如果标记帮助器组件类未被 ITagHelperComponentManager 管理,则必须向依赖注入(DI)系统注册。 以下Startup.ConfigureServices代码将AddressStyleTagHelperComponent和AddressScriptTagHelperComponent类注册为暂时性生存期:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<ITagHelperComponent,
AddressScriptTagHelperComponent>();
services.AddTransient<ITagHelperComponent,
AddressStyleTagHelperComponent>();
}
通过 Razor 文件注册
如果标记帮助程序组件未通过 DI 注册,则可以通过 Razor 页面或 MVC 视图来注册它。 这种技术用于从 Razor 文件中控制注入标记和组件执行顺序。
ITagHelperComponentManager 用于添加标记帮助程序组件或从应用中删除它们。 以下代码演示了此技术:AddressTagHelperComponent
@using RazorPagesSample.TagHelpers;
@using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
@inject ITagHelperComponentManager manager;
@{
string markup;
if (Model.IsWeekend)
{
markup = "<em class='text-warning'>Office closed today!</em>";
}
else
{
markup = "<em class='text-info'>Office open today!</em>";
}
manager.Components.Add(new AddressTagHelperComponent(markup, 1));
}
在前面的代码中:
- 该
@inject指令提供了ITagHelperComponentManager的实例。 该实例被分配给名为manager的变量,以便在Razor文件的下游访问。 - 应用的标签助手组件集合中添加了一个
AddressTagHelperComponent实例。
AddressTagHelperComponent 被修改以适应一个接受 markup 和 order 参数的构造函数:
private readonly string _markup;
public override int Order { get; }
public AddressTagHelperComponent(string markup = "", int order = 1)
{
_markup = markup;
Order = order;
}
在 markup 中使用提供的 ProcessAsync 参数,如下所示:
public override async Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "address",
StringComparison.OrdinalIgnoreCase) &&
output.Attributes.ContainsName("printable"))
{
TagHelperContent childContent = await output.GetChildContentAsync();
string content = childContent.GetContent();
output.Content.SetHtmlContent(
$"<div>{content}<br>{_markup}</div>{_printableButton}");
}
}
通过页面模型或控制器注册
如果未向 DI 注册标记帮助程序组件,则可以从 Razor 页面页面模型或 MVC 控制器注册它。 此方法可用于将 C# 逻辑与 Razor 文件分开。
构造函数注入用于访问ITagHelperComponentManager的实例。 Tag Helper组件被添加到实例的Tag Helper组件集合中。 以下 Razor Pages 页面模型通过以下方法 AddressTagHelperComponent演示了此技术:
using System;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesSample.TagHelpers;
public class IndexModel : PageModel
{
private readonly ITagHelperComponentManager _tagHelperComponentManager;
public bool IsWeekend
{
get
{
var dayOfWeek = DateTime.Now.DayOfWeek;
return dayOfWeek == DayOfWeek.Saturday ||
dayOfWeek == DayOfWeek.Sunday;
}
}
public IndexModel(ITagHelperComponentManager tagHelperComponentManager)
{
_tagHelperComponentManager = tagHelperComponentManager;
}
public void OnGet()
{
string markup;
if (IsWeekend)
{
markup = "<em class='text-warning'>Office closed today!</em>";
}
else
{
markup = "<em class='text-info'>Office open today!</em>";
}
_tagHelperComponentManager.Components.Add(
new AddressTagHelperComponent(markup, 1));
}
}
在前面的代码中:
- 构造函数注入用于访问
ITagHelperComponentManager的实例。 - 应用的标签助手组件集合中添加了一个
AddressTagHelperComponent实例。
创建组件
创建自定义标签助手组件
- 创建派生自 TagHelperComponentTagHelper的公共类。
- 将
[HtmlTargetElement]属性应用于类。 指定目标 HTML 元素的名称。 -
可选:向类应用
[EditorBrowsable(EditorBrowsableState.Never)]属性以禁止在 IntelliSense 中显示该类型。
以下代码创建特定于 <address> HTML 元素的自定义标记帮助程序组件:
using System.ComponentModel;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Logging;
namespace RazorPagesSample.TagHelpers
{
[HtmlTargetElement("address")]
[EditorBrowsable(EditorBrowsableState.Never)]
public class AddressTagHelperComponentTagHelper : TagHelperComponentTagHelper
{
public AddressTagHelperComponentTagHelper(
ITagHelperComponentManager componentManager,
ILoggerFactory loggerFactory) : base(componentManager, loggerFactory)
{
}
}
}
使用自定义address标记帮助器组件按如下所示注入HTML标记:
public class AddressTagHelperComponent : TagHelperComponent
{
private readonly string _printableButton =
"<button type='button' class='btn btn-info' onclick=\"window.open(" +
"'https://binged.it/2AXRRYw')\">" +
"<span class='glyphicon glyphicon-road' aria-hidden='true'></span>" +
"</button>";
public override int Order => 3;
public override async Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "address",
StringComparison.OrdinalIgnoreCase) &&
output.Attributes.ContainsName("printable"))
{
var content = await output.GetChildContentAsync();
output.Content.SetHtmlContent(
$"<div>{content.GetContent()}</div>{_printableButton}");
}
}
}
上述 ProcessAsync 方法将提供给 SetHtmlContent 的 HTML 注入到匹配的 <address> 元素中。 注入在以下情况下发生:
- 执行上下文的
TagName属性值等于address。 - 相应的
<address>元素具有属性printable。
例如,在处理以下if元素时,该<address>语句的计算结果为 true:
<address printable>
One Microsoft Way<br />
Redmond, WA 98052-6399<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>