Создание элементов Tag Helper

Rick Anderson

Вы можете найти исходный код на GitHub.

Начинаем создавать Tag Helpers

В этой статье мы научимся создавать Tag Helpers. В Введение в Тэг-хелперы (Tag Helpers) описаны преимущества Tag Helpers.

Tag Helper - это класс, который реализует интерфейс ITagHelper. Когда вы создаете Tag Helper, то обычно наследуете от TagHelper, что дает вам доступ к методу Process. Далее мы рассмотрим методы и свойства TagHelper.

  1. Создайте новый ASP.NET Core проект с именем AuthoringTagHelpers. Мы не будем использовать здесь аутентификацию.
  2. Создайте папку, где будут находиться Tag Helpers, назовите ее TagHelpers. Папка TagHelpers не обязательна, но по понятным причинам она соответствует соглашению. А теперь давайте попробуем создать несколько простых Tag Helpers.

Email Tag Helper

В этом разделе мы создадим Tag Helper, который обновляет тэг email. Например:

<email>Support</email>

Сервер будет использовать наш email Tag Helper, чтобы конвертировать разметку в следующую:

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

Notes:

  • Tag Helpers используют соглашение по именованию, и они нацелены на элементы, в которых используется имя класса минус TagHelper. В данном примере корневое имя EmailTagHelper - это email, так что они будут нацелены на тэг <email>. Это соглашение действительно для фактически всех Tag Helpers, но позже я покажу вам, как это переопределить.
  • Класс EmailTagHelper наследуется от TagHelper. Класс TagHelper предоставляет различные методы и свойства, которые мы позже изучим.
  • Переопределенный метод Process управляет тем, что будет делать Tag Helper после выполнения. Класс TagHelper также предоставляет асинхронную версию (ProcessAsync) с теми же параметрами.
  • Контекстный параметр для ProcessProcessAsync) содержит информацию, связанную с выполнением текущего HTML тэга.
  • Выходной параметр для ProcessProcessAsync) содержит представление stateful HTML элемента от исходного источника, который использовался для генерации HTML тэга и контента.
  • У нашего имени класса есть суффикс TagHelper, который не обязателен, но считается лучшим вариантом по соглашению. Вы можете объявить класс вот так:
public class Email : TagHelper
  1. Чтобы класс EmailTagHelper был доступен для всех представлений Razor, мы добавим директиву addTagHelper в файл Views/_ViewImports.cshtml:
@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper "*, AuthoringTagHelpers"

В коде сверху используется wildcard-синтаксис для указания всех доступных Tag Helpers с нашей сборке. Первая строка после @addTagHelper говорит, что надо загрузить Tag Helper (мы используем “*” для всех Tag Helpers), вторая строка “AuthoringTagHelpers” говорит сборке, что в ней есть Tag Helper. Также обратите внимание, что вторая строка передает ASP.NET Core MVC Tag Helpers с помощью wildcard-синтаксиса (см. Введение в Тэг-хелперы (Tag Helpers).) Директива @addTagHelper делает Tag Helper доступным для Razor представления. Кроме того, вы можете передать полное имя (FQN) Tag Helper, как показано ниже:

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

Чтобы добавить Tag Helper в представление с помощью FQN, вы сперва добавляете FQN (AuthoringTagHelpers.TagHelpers.EmailTagHelper), а затем имя сборки (AuthoringTagHelpers). Большинство разработчиков предпочитают использовать wildcard-синтаксис. См. Введение в Тэг-хелперы (Tag Helpers).

  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>
  1. Запустите приложение и используйте браузер, чтобы просмотреть исходник HTML, и вы убедитесь, что имейл тэги заменены якорной разметкой (например, <a>Support</a>). Support и Marketing представлены как ссылки, но у них нет атрибута href, чтобы они могли работать. В следующем разделе мы это исправим.

Note: Как и HTML тэги и атрибуты, тэги, имена классов и атрибутов в Razor и C# ну чувствительны к регистру.

Рабочий email Tag Helper

В этом разделе мы обновим EmailTagHelper, так чтобы он мог создать валидный якорный тэг для имейла. Наш Tag Helper будет принимать информацию из представления Razor (в форме атрибута mail-to) и использовать ее для генерации якоря.

Обновите класс EmailTagHelper:

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

    // Can be passed via <email mail-to="..." />. 
    // Pascal case gets translated into lower-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);
    }
}

Notes:

  • Имена классов и свойств PascalСase для Tag Helpers превращаются в lower kebab case. Поэтому, чтобы использовать атрибут MailTo, нам нужно использовать эквивалент <email mail-to="value"/>.
  • Следующая строка устанавливает завершенный контент для минимально функционирующего Tag Helper.
  • В следующей строке представлен синтаксис для добавления атрибутов:
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”, если он на данный момент не существует в текущей коллекции атрибутов. Вы также можете использовать метод output.Attributes.Add, чтобы добавить атрибут Tag Helper в конец коллекции атрибутов тэгов.

  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>
  1. Запустите приложение и проверьте, что здесь генерируются корректные ссылки.

Note: Если вы хотите, чтобы тэг email был одинарным (<email mail-to="Rick" />), то и на выходе тэг будет одинарным. Чтобы иметь возможность прописывать только начальный тэг (<email mail-to="Rick">), вы должны добавить следующий код:

[HtmlTargetElement("email", TagStructure = TagStructure.WithoutEndTag)] 

С одинарным email Tag Helper на выходе вы получите <a href="mailto:Rick@contoso.com" />. Одинарные якорные тэги не являются валидным HTML, так что вы не будете создавать такие, но, возможно, вы захотите создать одинарный Tag Helper. Tag Helpers устанавливают тип свойства TagMode после прочтения тэга.

Асинхронный email Helper

В этом разделе мы напишем асинхронный email Helper.

  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 возвращает Task, содержащий TagHelperContent.
  • Мы используем параметр output, чтобы получить контекст HTML элемента.
  1. Внесите следующее изменение в файл Views/Home/Contact.cshtml, чтобы Tag Helper мог получить целевой имейл.
@{
    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>
  1. Запустите приложение и проверьте, что оно генерирует валидные имейл ссылки.

Bold Tag Helper

  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>");
        }
    }
}

/*
 * public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";
    return View("AboutBoldOnly");
    // return View();
}
*/

Notes:

  • Атрибут [HtmlTargetElement] передает параметр, который указывает, что надо искать HTML элементы, содержащие HTML атрибут со значением “bold”, и в классе будет запущен метод Process. В нашем примере метод Process удаляет “bold” и окружает содержащуюся разметку тэгами <strong></strong>.
  • Поскольку мы не хотим заменять существующий контент тэгов, мы должны записать открывающий тэг <strong> с помощью метода PreContent.SetHtmlContent, а закрывающий </strong> - с помощью PostContent.SetHtmlContent.
  1. Измените представление 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>
  1. Запустите приложение. Исследуйте в браузере исходный код, чтобы увидеть, что разметка изменилась.

Атрибут [HtmlTargetElement] касается только HTML разметки, где есть атрибут “bold”. А вот элемент <bold> Tag Helper не меняет.

  1. Закомментируйте [HtmlTargetElement], и тогда тэги <bold> войдут в игру. Помните, что имя класса BoldTagHelper будет соответствовать тэгам <bold>.
  2. Запустите приложение и проверьте, что тэг <bold> обрабатывается Tag Helper.

Если использовать код, представленный ниже, тэг bold и атрибут bold будут подходить нашей цели.

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

Если несколько атрибутов добавлены в одно и то же выражение, они обрабатываются как logical-AND (логическое И). Например, в коде снизу HTML элемент должен быть назван “bold” и иметь атрибут “bold” ( <bold bold /> ), чтобы подходить нашей цели.

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

Вы также можете использовать [HtmlTargetElement], чтобы сменить имя целевого элемента. Например, если вы хотите, чтобы BoldTagHelper был нацелен на <MyBold>, вам нужно использовать следующий атрибут:

[HtmlTargetElement("MyBold")]

Информационный Tag Helper

  1. Добавьте папку Models.
  2. Добавьте в эту папку класс WebsiteContext:
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; }
    }
}
  1. Добавьте класс 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;
      }
   }
}

Notes:

  • Tag Helpers превращают имена классов и свойств PascalСase в lower kebab case. Поэтому чтобы использовать WebsiteInformationTagHelper в Razor, вы напишете <website-information />.
  • Мы не явно определяем целевой элемент с помощью атрибута [HtmlTargetElement], так что целью будет website-information по умолчанию. Если вы примените следующий атрибут:
[HtmlTargetElement("WebsiteInformation")]

то тэг <website-information /> не подойдет. Если вы хотите использовать атрибут [HtmlTargetElement], то будете использовать kebab case, как показано ниже:

[HtmlTargetElement("Website-Information")]
  • У элементов с одинарными тэгами нет контента. В этом примере в Razor разметке будет использоваться одинарный тэг, но Tag Helper создаст элемент section (у которого есть открывающий и закрывающий тэги, и мы добавим в элемент section контент). Поэтому мы должны установить TagMode на StartTagAndEndTag, чтобы вывести результат. Кроме того, вы можете закомментировать TagMode и прописать в разметке закрывающий тэг.
  • Знак доллара $ в следующей строке используется для интерполированной строки:
$@"<ul><li><strong>Version:</strong> {Info.Version}</li>
  1. Добавьте следующую разметку в представление About.cshtml. Выделенная разметка отображает информацию веб сайта.
@using AuthoringTagHelpers.Models
@{
    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>

<h3> web site info </h3>
<website-information info="new WebsiteContext {
                                    Version = new Version(1, 3),
                                    CopyrightYear = 1638,
                                    Approved = true,
                                    TagsToShow = 131 }" />

Note: В Razor разметке, показанной ниже:

<website-information info="new WebsiteContext {
                                    Version = new Version(1, 3),
                                    CopyrightYear = 1638,
                                    Approved = true,
                                    TagsToShow = 131 }" />

Razor знает, что info - это объект, а не строка. Любой не строковой атрибут Tag Helper должен быть прописан без символа @.

  1. Запустите приложение и перейдите к представлению About, чтобы увидеть информацию веб сайта.

Note:

  • Вы можете использовать следующую разметку с закрывающим тэгом и удалить строку с TagMode.StartTagAndEndTag в Tag Helper:
<website-information info="new WebsiteContext {
                                    Version = new Version(1, 3),
                                    CopyrightYear = 1638,
                                    Approved = true,
                                    TagsToShow = 131 }" >
</website-information>

Tag Helper условия

Tag Helper условия отображает выходные данные, если передается значение 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();
            }
        }
    }
}
  1. Замените контекст файла 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>
  1. Замените метод Index в контроллере Home следующим кодом:
  public IActionResult Index(bool approved = false)
  {
      return View(new WebsiteContext
      {
          Approved = approved,
          CopyrightYear = 2015,
          Version = new Version(1, 3, 3, 7),
          TagsToShow = 20
      });
  }
  1. Запустите приложение и перейдите к домашней странице. Разметка в условном div не будет отображена. Добавьте к URL строку запроса ?approved=true (например, http://localhost:1235/Home/Index?approved=true). Тогда условная разметка будет отображена.

Note: Мы используем оператор nameof, чтобы указать целевой атрибут, а не строку, как мы делали с bold Tag Helper:

[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).

Как избежать конфликта между элементами Tag Helper

В этом разделе мы создадим пару перекрещивающихся Tag Helpers. Первый заменит разметку, содержащую URL, начиная с HTTP и заканчивая якорным тэгом HTML, содержащим тот же URL. Второй будет работать с тем же URL, начиная с WWW.

Поскольку оба хелпера тесно связаны и мы сможем провести их рефакторинг в будущем, мы оставим их в одном файле.

  1. Добавьте класс AutoLinker в папку 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}
    }
}

Notes: Класс AutoLinkerHttpTagHelper нацелен на элементы p и использует Regex, чтобы создать якорь.

  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>

<p>Visit us at http://docs.asp.net or at www.microsoft.com</p>
  1. Запустите приложение и проверьте, что Tag Helper отображает якорь корректно.
  2. Обновите класс 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
    }
}
  1. Запустите приложение. Обратите внимание, что www текст отображается как ссылка, а HTTP текст нет. Если вы установите точку останова в обоих классах, то увидите, что класс HTTP Tag Helper запускается первым. Далее мы рассмотрим, как определять порядок, в котором запускаются Tag Helpers. Проблема состоит в том, что выходные данные Tag Helper кэшируются, и когда запускается WWW Tag Helper, он переписывает кэшированные данные из HTTP Tag Helper. Мы исправим это с помощью данного кода:
    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: В первой редакции перекрещивающихся Tag Helpers мы получали контент целевого элемента с помощью следующего кода:

var childContent = await output.GetChildContentAsync();

Это GetChildContentAsync, который использует TagHelperOutput, переданный методу ProcessAsync. Поскольку выходные данные кэшируются, последний запущенный Tag Helper “побеждает”. Это можно исправить с помощью следующего кода:

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

Код выше проверяет, был ли изменен контент, и если был, он получает контент из буфера.

  1. Запустите приложение и проверьте, что две ссылки работают так, как и ожидалось. Но все же у нас есть небольшая проблема. Если WWW Tag Helper запускается первым, ссылки www не будут правильными. Нам нужно обновить код, добавив Order, чтобы контролировать порядок, в котором запускаются тэги. Свойство Order определяет порядок выполнения по отношению к другим Tag Helpers, нацеленным на один и тот же элемент. Значение по умолчанию равно нулю, и экземпляры с меньшими значениями выполняются первыми.
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;   }
    }

Код выше делает так, что WWW Tag Helper запускается перед HTTP Tag Helper. Измените Order на MaxValue, и вы увидите, что разметка, сгенерированная для WWW тэга является неверной.

Изучение и получение дочернего контента

У элементов Tag Helper есть несколько свойств для получения контента.

  • Результат GetChildContentAsync может быть присоединен к output.Content.
  • Вы можете изучить результат GetChildContentAsync с помощью GetContent.
  • Если вы измените 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, пока вы не передадите неправильный параметр, показывающий, что кэшированные результаты не используются.

Поделись хорошей новостью с друзьями!
Следи за новостями!