在 ASP.NET Core 中编写标记帮助程序

作者 Rick Anderson

查看或下载示例代码(如何下载)

Tag Helper 入门

本教程介绍 Tag Helper 编程。 Tag Helper 简介描述了 Tag Helper 提供的优势。

标记帮助程序是实现 ITagHelper 接口的任何类。 但是,在编写 Tag Helper 时,通常从 TagHelper 派生,这样可以访问 Process 方法。

  1. 创建一个名为 AuthoringTagHelpers 的新 ASP.NET Core 项目。 此项目不需要身份验证。

  2. 创建一个名为TagHelpers的文件夹来保存标记帮助程序。 TagHelpers 文件夹不是必需的,但它是合理的约定。 现在让我们开始编写一些简单的标记帮助器。

最小的 Tag Helper

在本部分中,你将编写一个更新 email 标签的标记帮助程序。 例如:

<email>Support</email>

服务器将使用电子邮件标记帮助程序将该标记转换为以下内容:

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

即,使其成为电子邮件链接的锚点标签。 如果你正在编写博客引擎,并且需要它将营销、支持和其他联系用途的电子邮件全部发送到同一个域,则可能需要执行此操作。

  1. 将以下 EmailTagHelper 类添加到“TagHelpers”文件夹。

    
    using Microsoft.AspNetCore.Razor.TagHelpers;
    using System.Threading.Tasks;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        public class EmailTagHelper : TagHelper
        {
            public override void Process(TagHelperContext context, TagHelperOutput output)
            {
                output.TagName = "a";    // Replaces <email> with <a> tag
            }
        }
    }
    
    • 标记帮助程序使用一种命名约定,以根类名称的元素为目标(减去类名称中的 TagHelper 部分)。 在此示例中,EmailTagHelper 的根名称是 email,因此将以 标记为目标。 此命名约定应适用于大多数标记帮助程序,稍后将介绍如何重写它。

    • EmailTagHelper 类从 TagHelper 派生。 TagHelper 类提供用于编写 Tag Helper 的方法和属性。

    • 重写的 Process 方法控制标记帮助程序在执行时的操作。 TagHelper 类还提供具有相同参数的异步版本 (ProcessAsync)。

    • Process(和 ProcessAsync)的上下文参数包含与执行当前 HTML 标记相关的信息。

    • Process(和 ProcessAsync)的输出参数包含一个有状态的 HTML 元素,它代表用于生成 HTML 标记和内容的原始源内容。

    • 类名称的后缀是 TagHelper,这不是必需的,但被认为是最佳做法约定。 可将类声明为:

    public class Email : TagHelper
    
  2. 要使 EmailTagHelper 类可用于所有 Razor 视图,请将 addTagHelper 指令添加到 Views/_ViewImports.cshtml 文件:

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

    上面的代码使用通配符语法来指定程序集中的所有标记帮助程序都将可用。 @addTagHelper 之后的第一个字符串指定要加载的标记帮助程序(对所有标记帮助程序使用“*”),第二个字符串“AuthoringTagHelpers”指定标记帮助程序所在的程序集。 另请注意,第二行使用通配符语法引入了 ASP.NET Core MVC 标记帮助程序(这些帮助程序在 标记帮助程序简介 中进行了讨论)。是 @addTagHelper 指令使标记帮助程序可用于 Razor 视图。 或者,也可以提供标记帮助程序的完全限定的名称 (FQN),如下所示:

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

若要使用 FQN 将标记帮助程序添加到视图中,请先添加 FQN (AuthoringTagHelpers.TagHelpers.EmailTagHelper),然后再添加 程序集名称(AuthoringTagHelpers,不一定是 )。 大多数开发者更喜欢使用通配符语法。 标记帮助程序简介详细介绍了标记帮助程序的添加和删除方法,以及层次结构和通配符语法。

  1. 使用以下更改更新 Views/Home/Contact.cshtml 文件中的标记:

    @{
        ViewData["Title"] = "Contact";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <address>
        One Microsoft Way<br />
        Redmond, WA 98052<br />
        <abbr title="Phone">P:</abbr>
        425.555.0100
    </address>
    
    <address>
        <strong>Support:</strong><email>Support</email><br />
        <strong>Marketing:</strong><email>Marketing</email>
    </address>
    
  2. 运行应用并使用你喜爱的浏览器来查看 HTML 源,以便验证电子邮件标签是否替换为锚点标记(例如,<a>Support</a>)。 Support 和 Marketing 呈现为链接,但它们没有使其生效的 href 属性。 我们将在下一部分解决这个问题。

SetAttribute 和 SetContent

在本部分中,我们将更新 EmailTagHelper,使其能够创建用于电子邮件的有效锚标签。 我们将对其进行更新以获取 Razor 视图中的信息(采用 mail-to 属性的形式)并使用该信息来生成锚点。

使用以下内容更新 EmailTagHelper 类:

public class EmailTagHelper : TagHelper
{
    private const string EmailDomain = "contoso.com";

    // Can be passed via <email mail-to="..." />. 
    // PascalCase gets translated into kebab-case.
    public string MailTo { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";    // Replaces <email> with <a> tag

        var address = MailTo + "@" + EmailDomain;
        output.Attributes.SetAttribute("href", "mailto:" + address);
        output.Content.SetContent(address);
    }
}
  • 标记帮助程序采用 Pascal 大小写格式的类和属性名将转换为短横线格式。 因此,要使用 MailTo 属性,请使用与 <email mail-to="value"/> 对应的项。

  • 最后一行为我们这个仅具备最基本功能的标记帮助程序设置完整内容。

  • 突出显示的行显示了添加属性的语法:

public override void Process(TagHelperContext context, TagHelperOutput output)
{
    output.TagName = "a";    // Replaces <email> with <a> tag

    var address = MailTo + "@" + EmailDomain;
    output.Attributes.SetAttribute("href", "mailto:" + address);
    output.Content.SetContent(address);
}

只要属性集合中当前不存在“href”属性,这种做法就对“href”属性适用。 也可使用 output.Attributes.Add 方法将标记帮助程序属性添加到标记属性集合的末尾。

  1. 使用以下更改更新 Views/Home/Contact.cshtml 文件内的标记:

    @{
        ViewData["Title"] = "Contact Copy";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <address>
        One Microsoft Way Copy Version <br />
        Redmond, WA 98052-6399<br />
        <abbr title="Phone">P:</abbr>
        425.555.0100
    </address>
    
    <address>
        <strong>Support:</strong><email mail-to="Support"></email><br />
        <strong>Marketing:</strong><email mail-to="Marketing"></email>
    </address>
    
  2. 运行应用并验证它是否生成正确的链接。

Note

如果将电子邮件标签写成自闭合形式(<email mail-to="Rick" />),最终输出也将是自闭合的。 要启用仅使用起始标记(<email mail-to="Rick">)来编写该标签的功能,必须使用以下内容来标记该类:

[HtmlTargetElement("email", TagStructure = TagStructure.WithoutEndTag)] 
public class EmailVoidTagHelper : TagHelper
{
    private const string EmailDomain = "contoso.com";
    // Code removed for brevity

使用自闭合的电子邮件标记帮助程序时,输出将为 <a href="mailto:Rick@contoso.com" />。 自结束锚点标签不是有效的 HTML,因此你不想创建这样的标签,但你可能想要创建一个自结束的标记帮助器。 标记帮助程序在读取标记后设置 TagMode 属性的类型。

还可以使用 [HtmlAttributeName] attribute将不同的 attribute 名称映射到属性。

将名为 recipient 的特性映射到 MailTo 属性:

[HtmlAttributeName("recipient")]
public string? MailTo { get; set; }

recipient 特性的标记帮助程序:

<email recipient="…"/>

ProcessAsync

在本部分中,我们将编写异步电子邮件帮助程序。

  1. 将 EmailTagHelper 类替换为以下代码:

    public class EmailTagHelper : TagHelper
    {
        private const string EmailDomain = "contoso.com";
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "a";                                 // Replaces <email> with <a> tag
            var content = await output.GetChildContentAsync();
            var target = content.GetContent() + "@" + EmailDomain;
            output.Attributes.SetAttribute("href", "mailto:" + target);
            output.Content.SetContent(target);
        }
    }
    

    Notes:

    • 此版本使用异步 ProcessAsync 方法。 异步 GetChildContentAsync 返回一个包含 TagHelperContent 的 Task。

    • 使用 output 参数获取 HTML 元素的内容。

  2. 对 Views/Home/Contact.cshtml 文件进行以下更改,以便标记帮助程序能够获取目标电子邮件。

    @{
        ViewData["Title"] = "Contact";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <address>
        One Microsoft Way<br />
        Redmond, WA 98052<br />
        <abbr title="Phone">P:</abbr>
        425.555.0100
    </address>
    
    <address>
        <strong>Support:</strong><email>Support</email><br />
        <strong>Marketing:</strong><email>Marketing</email>
    </address>
    
  3. 运行应用并验证它是否生成有效的电子邮件链接。

RemoveAll、PreContent.SetHtmlContent 和 PostContent.SetHtmlContent

  1. 将以下 BoldTagHelper 类添加到“TagHelpers”文件夹。

    using Microsoft.AspNetCore.Razor.TagHelpers;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        [HtmlTargetElement(Attributes = "bold")]
        public class BoldTagHelper : TagHelper
        {
            public override void Process(TagHelperContext context, TagHelperOutput output)
            {
                output.Attributes.RemoveAll("bold");
                output.PreContent.SetHtmlContent("<strong>");
                output.PostContent.SetHtmlContent("</strong>");
            }
        }
    }
    
    • [HtmlTargetElement] 属性传递一个属性参数,该参数指定包含名为“bold”的 HTML 属性的任何 HTML 元素都将匹配,并且该类中的 Process 重写方法将会运行。 在此示例中,Process 方法删除了“bold”属性,并用 <strong></strong> 包裹包含该属性的标记。

    • 因为你不想替换现有的标记内容,所以必须用 PreContent.SetHtmlContent 方法编写开头的 <strong> 标记,并用 PostContent.SetHtmlContent 方法编写结尾的 </strong> 标记。

  2. 修改 About.cshtml 视图,以包含 bold 特性值。 完成的代码如下所示。

    @{
        ViewData["Title"] = "About";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <p bold>Use this area to provide additional information.</p>
    
    <bold> Is this bold?</bold>
    
  3. 运行应用。 可以使用你喜爱的浏览器来检查源代码并验证标记。

    上面的 [HtmlTargetElement] 属性仅针对提供属性名称“bold”的 HTML 标记。 标记帮助程序未修改 <bold> 元素。

  4. 将 [HtmlTargetElement] 属性行注释掉,它将默认以 <bold> 标记为目标,也就是形如 <bold> 的 HTML 标记。 请记住,默认命名约定会将类名 BoldTagHelper 与 <bold> 标记相匹配。

  5. 运行应用并验证 <bold> 标记是否由标记帮助程序进行处理。

用多个 [HtmlTargetElement] 属性修饰类会使这些目标按逻辑 OR 组合。 例如,使用下面的代码时,系统将匹配出 bold 标记或 bold 属性。

[HtmlTargetElement("bold")]
[HtmlTargetElement(Attributes = "bold")]
public class BoldTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes.RemoveAll("bold");
        output.PreContent.SetHtmlContent("<strong>");
        output.PostContent.SetHtmlContent("</strong>");
    }
}

将多个属性添加到同一语句时,运行时会将其视为逻辑 AND。 例如,在下面的代码中,HTML 元素必须命名为“bold”并具有名为“bold”的属性 (<bold bold />) 才能匹配。

[HtmlTargetElement("bold", Attributes = "bold")]

也可使用 [HtmlTargetElement] 更改目标元素的名称。 例如,如果你希望 BoldTagHelper 针对 <MyBold> 标记,则可使用以下属性:

[HtmlTargetElement("MyBold")]

将模型传递到标记帮助程序

  1. 添加 Models 文件夹。

  2. 将以下 WebsiteContext 类添加到“Models”文件夹:

    using System;
    
    namespace AuthoringTagHelpers.Models
    {
        public class WebsiteContext
        {
            public Version Version { get; set; }
            public int CopyrightYear { get; set; }
            public bool Approved { get; set; }
            public int TagsToShow { get; set; }
        }
    }
    
  3. 将以下 WebsiteInformationTagHelper 类添加到 TagHelpers 文件夹中。

    using System;
    using AuthoringTagHelpers.Models;
    using Microsoft.AspNetCore.Razor.TagHelpers;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        public class WebsiteInformationTagHelper : TagHelper
        {
            public WebsiteContext Info { get; set; }
    
          public override void Process(TagHelperContext context, TagHelperOutput output)
          {
             output.TagName = "section";
             output.Content.SetHtmlContent(
    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    <li><strong>Copyright Year:</strong> {Info.CopyrightYear}</li>
    <li><strong>Approved:</strong> {Info.Approved}</li>
    <li><strong>Number of tags to show:</strong> {Info.TagsToShow}</li></ul>");
             output.TagMode = TagMode.StartTagAndEndTag;
          }
       }
    }
    
    • 如前所述,标记帮助器会将标记帮助器采用 Pascal 大小写格式的 C# 类名和属性转换为短横线格式。 因此,要使用 Razor 中的 WebsiteInformationTagHelper,请编写 <website-information />。

    • 未显式使用 [HtmlTargetElement] 属性标识目标元素,因此默认将以 website-information 为目标。 如果应用了以下属性(请注意,它虽不是短横线格式,但却与类名相匹配):

    [HtmlTargetElement("WebsiteInformation")]
    

    短横线格式标记 <website-information /> 将无法匹配。 若要使用 [HtmlTargetElement] 属性,请使用短横线格式,如下所示:

    [HtmlTargetElement("Website-Information")]
    
    • 自结束的元素没有任何内容。 在此示例中,Razor 标记将使用自结束标记,但标记帮助程序将创建 section 元素(这不是自结束元素,并且你正在 section 元素中编写内容)。 因此,需要将 TagMode 设置为 StartTagAndEndTag 以写入输出。 或者,可以将设置 TagMode 的那一行注释掉,并使用闭合标签编写标记。 (本教程后面将提供标记示例。)

    • 下一行中的 $(美元符号)使用内插字符串:

    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    
  4. 将以下标记添加到 About.cshtml 视图中。 突出显示的标记显示 Web 站点信息。

    @using AuthoringTagHelpers.Models
    @{
        ViewData["Title"] = "About";
        WebsiteContext webContext = new WebsiteContext {
                                        Version = new Version(1, 3),
                                        CopyrightYear = 1638,
                                        Approved = true,
                                        TagsToShow = 131 };
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <p bold>Use this area to provide additional information.</p>
    
    <bold> Is this bold?</bold>
    
    <h3> web site info </h3>
    <website-information info="webContext" />
    

    Note

    在下面显示的 Razor 标记代码中:

    <website-information info="webContext" />
    

    Razor 知道 info 属性是一个类,而不是字符串,并且你想要编写 C# 代码。 编写任何非字符串标记帮助程序属性时,都不应使用 @ 字符。

  5. 运行应用,并导航到“关于”视图查看 Web 站点信息。

    Note

    可使用带有结束标记的以下标记,并在标记帮助程序中删除带有 TagMode.StartTagAndEndTag 的行:

    <website-information info="webContext" >
    </website-information>
    

条件标记帮助器

条件标记帮助程序在传递 true 值时呈现输出。

  1. 将以下 ConditionTagHelper 类添加到“TagHelpers”文件夹。

    using Microsoft.AspNetCore.Razor.TagHelpers;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        [HtmlTargetElement(Attributes = nameof(Condition))]
        public class ConditionTagHelper : TagHelper
        {
            public bool Condition { get; set; }
    
            public override void Process(TagHelperContext context, TagHelperOutput output)
            {
                if (!Condition)
                {
                    output.SuppressOutput();
                }
            }
        }
    }
    
  2. 将 Views/Home/Index.cshtml 文件的内容替换为以下标记:

    @using AuthoringTagHelpers.Models
    @model WebsiteContext
    
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div>
        <h3>Information about our website (outdated):</h3>
        <Website-InforMation info="Model" />
        <div condition="Model.Approved">
            <p>
                This website has <strong surround="em">@Model.Approved</strong> been approved yet.
                Visit www.contoso.com for more information.
            </p>
        </div>
    </div>
    
  3. 将 Home 控制器中的 Index 方法替换为以下代码:

    public IActionResult Index(bool approved = false)
    {
        return View(new WebsiteContext
        {
            Approved = approved,
            CopyrightYear = 2015,
            Version = new Version(1, 3, 3, 7),
            TagsToShow = 20
        });
    }
    
  4. 运行应用并浏览到主页。 条件 div 中的标记不会渲染。 将查询字符串 ?approved=true 追加到 URL(例如,http://localhost:1235/Home/Index?approved=true)。 approved 设置为 true,并将显示条件标记内容。

Note

使用 nameof 运算符指定要作为目标的属性,而不是像使用 bold 标记帮助程序那样指定字符串:

[HtmlTargetElement(Attributes = nameof(Condition))]
 //   [HtmlTargetElement(Attributes = "condition")]
 public class ConditionTagHelper : TagHelper
{
   public bool Condition { get; set; }

   public override void Process(TagHelperContext context, TagHelperOutput output)
   {
      if (!Condition)
      {
         output.SuppressOutput();
      }
   }
}

如果代码被重构,nameof 运算符将保护它(可能需要将名称更改为 RedCondition)。

避免标记帮助程序冲突

在本部分中,你将编写一对自动链接标记帮助程序。 第一个将会把包含以 HTTP 开头的 URL 的标记替换为包含相同 URL 的 HTML 定位标记(从而产生指向该 URL 的链接)。 第二个标记帮助程序也会对以 WWW 开头的 URL 执行相同的操作。

由于这两个帮助程序密切相关,并且你将来可能会重构它们,因此可将其保存在同一文件中。

  1. 将以下 AutoLinkerHttpTagHelper 类添加到“TagHelpers”文件夹。

    [HtmlTargetElement("p")]
    public class AutoLinkerHttpTagHelper : TagHelper
    {
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var childContent = await output.GetChildContentAsync();
            // Find Urls in the content and replace them with their anchor tag equivalent.
            output.Content.SetHtmlContent(Regex.Replace(
                 childContent.GetContent(),
                 @"\b(?:https?://)(\S+)\b",
                  "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
        }
    }
    

    Note

    AutoLinkerHttpTagHelper 类以 p 元素为目标,并使用正则表达式来创建锚点。

  2. 在 Views/Home/Contact.cshtml 文件末尾添加以下标记:

    @{
        ViewData["Title"] = "Contact";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <address>
        One Microsoft Way<br />
        Redmond, WA 98052<br />
        <abbr title="Phone">P:</abbr>
        425.555.0100
    </address>
    
    <address>
        <strong>Support:</strong><email>Support</email><br />
        <strong>Marketing:</strong><email>Marketing</email>
    </address>
    
    <p>Visit us at http://docs.asp.net or at www.microsoft.com</p>
    
  3. 运行应用并验证标记帮助程序是否正确呈现锚点。

  4. 更新 AutoLinker 类以包含 AutoLinkerWwwTagHelper,这会将 www 文本转换为还包含原始 www 文本的锚点标签。 更新后的代码在下方突出显示:

        [HtmlTargetElement("p")]
        public class AutoLinkerHttpTagHelper : TagHelper
        {
            public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
            {
                var childContent = await output.GetChildContentAsync();
                // Find Urls in the content and replace them with their anchor tag equivalent.
                output.Content.SetHtmlContent(Regex.Replace(
                     childContent.GetContent(),
                     @"\b(?:https?://)(\S+)\b",
                      "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
            }
        }
    
        [HtmlTargetElement("p")]
        public class AutoLinkerWwwTagHelper : TagHelper
        {
            public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
            {
                var childContent = await output.GetChildContentAsync();
                // Find Urls in the content and replace them with their anchor tag equivalent.
                output.Content.SetHtmlContent(Regex.Replace(
                    childContent.GetContent(),
                     @"\b(www\.)(\S+)\b",
                     "<a target=\"_blank\" href=\"http://$0\">$0</a>"));  // www version
            }
        }
    }
    
  5. 运行应用。 请注意,www 文本呈现为链接,但 HTTP 文本并未呈现为链接。 如果将中断点放在这两个类中,可以看到 HTTP 标记帮助程序类首先运行。 问题是,标记帮助程序输出已缓存,当运行 WWW 标记帮助程序时,它会覆盖 HTTP 标记帮助程序的缓存输出。 本教程稍后将介绍如何控制标记帮助程序的运行顺序。 我们将用以下方法修复代码:

      public class AutoLinkerHttpTagHelper : TagHelper
      {
          public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
          {
              var childContent = output.Content.IsModified ? output.Content.GetContent() :
                  (await output.GetChildContentAsync()).GetContent();
    
              // Find Urls in the content and replace them with their anchor tag equivalent.
              output.Content.SetHtmlContent(Regex.Replace(
                   childContent,
                   @"\b(?:https?://)(\S+)\b",
                    "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
          }
      }
    
      [HtmlTargetElement("p")]
      public class AutoLinkerWwwTagHelper : TagHelper
      {
          public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
          {
              var childContent = output.Content.IsModified ? output.Content.GetContent() : 
                  (await output.GetChildContentAsync()).GetContent();
    
              // Find Urls in the content and replace them with their anchor tag equivalent.
              output.Content.SetHtmlContent(Regex.Replace(
                   childContent,
                   @"\b(www\.)(\S+)\b",
                   "<a target=\"_blank\" href=\"http://$0\">$0</a>"));  // www version
          }
      }
    

    Note

    在自动链接标记帮助程序的第一版中,你可以使用以下代码获取目标的内容:

    var childContent = await output.GetChildContentAsync();
    

    也就是说,使用传递到 ProcessAsync 方法中的 TagHelperOutput 调用 GetChildContentAsync。 如前所述,由于输出已缓存,因此最后运行的标记帮助程序会生效。 你用以下代码解决了这个问题:

    var childContent = output.Content.IsModified ? output.Content.GetContent() : 
        (await output.GetChildContentAsync()).GetContent();
    

    上面的代码检查内容是否已修改,如果已修改,则从输出缓冲区获取内容。

  6. 运行应用并验证这两个链接是否按预期工作。 虽然它可能看起来自动链接器标记帮助程序是正确且完整的,但它有一个细微的问题。 如果首先运行 WWW 标记帮助程序,则 www 链接不正确。 通过添加 Order 重载更新代码来控制标记运行的顺序。 Order 属性确定相对于面向同一元素的其他标记帮助程序的执行顺序。 默认顺序值为零,并首先执行具有较低值的实例。

    public class AutoLinkerHttpTagHelper : TagHelper
    {
        // This filter must run before the AutoLinkerWwwTagHelper as it searches and replaces http and 
        // the AutoLinkerWwwTagHelper adds http to the markup.
        public override int Order
        {
            get  {  return int.MinValue;   }
        }
    

    上面的代码可以保证 HTTP 标记帮助程序在 WWW 标记帮助程序之前运行。 将 Order 更改为 MaxValue,并验证为 WWW 标记生成的标记是否有误。

检查和检索子内容

标记帮助程序提供多个属性来检索内容。

  • 可将 GetChildContentAsync 的结果追加到 output.Content。
  • 可使用 GetContent 检查 GetChildContentAsync 的结果。
  • 如果修改 output.Content,则不会执行或呈现 TagHelper 主体,除非像自动链接器示例中那样调用 GetChildContentAsync:
public class AutoLinkerHttpTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        var childContent = output.Content.IsModified ? output.Content.GetContent() :
            (await output.GetChildContentAsync()).GetContent();

        // Find Urls in the content and replace them with their anchor tag equivalent.
        output.Content.SetHtmlContent(Regex.Replace(
             childContent,
             @"\b(?:https?://)(\S+)\b",
              "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
    }
}
  • 对 GetChildContentAsync 的多次调用返回相同的值,且不重新执行 TagHelper 主体,除非传入一个指示不使用缓存结果的 false 参数。

加载压缩的分部视图 TagHelper

在生产环境中,可以通过加载压缩的局部视图来提升性能。 若要在生产环境中利用缩小的分部视图,请执行以下操作:

  • 创建/设置压缩部分视图的预构建过程。
  • 使用以下代码在非开发环境中加载压缩的分部视图。
public class MinifiedVersionPartialTagHelper : PartialTagHelper
    {
        public MinifiedVersionPartialTagHelper(ICompositeViewEngine viewEngine, 
                                IViewBufferScope viewBufferScope)
                               : base(viewEngine, viewBufferScope)
        {

        }

        public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            // Append ".min" to load the minified partial view.
            if (!IsDevelopment())
            {
                Name += ".min";
            }

            return base.ProcessAsync(context, output);
        }

        private bool IsDevelopment()
        {
            return Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") 
                                                 == EnvironmentName.Development;
        }
    }