Tworzenie pomocników tagów w programie ASP.NET Core

Autor: Rick Anderson

Wyświetl lub pobierz przykładowy kod (jak pobrać)

Wprowadzenie do pomocników tagów

Ten samouczek zawiera wprowadzenie do pomocników tagów programowania. Wprowadzenie do pomocników tagów opisuje korzyści zapewniane przez pomocników tagów.

Pomocnik tagów to dowolna klasa, która implementuje ITagHelper interfejs. Jednak podczas tworzenia pomocnika tagów zazwyczaj pochodzisz z TagHelpermetody , dzięki czemu uzyskujesz dostęp do Process metody .

  1. Utwórz nowy projekt ASP.NET Core o nazwie AuthoringTagHelpers. W tym projekcie nie będzie potrzebne uwierzytelnianie.

  2. Utwórz folder do przechowywania pomocników tagów o nazwie TagHelpers. Folder TagHelpers nie jest wymagany, ale jest to rozsądna konwencja. Teraz zacznijmy pisać kilka prostych pomocników tagów.

Pomocnik tagu minimalnego

W tej sekcji napiszesz pomocnik tagu, który aktualizuje tag e-mail. Przykład:

<email>Support</email>

Serwer użyje naszego pomocnika tagów poczty e-mail, aby przekonwertować ten znacznik na następujące elementy:

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

Oznacza to, że tag kotwicy, który sprawia, że jest to link do wiadomości e-mail. Możesz to zrobić, jeśli piszesz aparat blogów i potrzebujesz go do wysyłania wiadomości e-mail na potrzeby marketingu, pomocy technicznej i innych kontaktów, a wszystko to do tej samej domeny.

  1. Dodaj następującą EmailTagHelper klasę do folderu 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
            }
        }
    }
    
    • Pomocnicy tagów używają konwencji nazewnictwa, która jest przeznaczona dla elementów nazwy klasy głównej (minus część TagHelper nazwy klasy). W tym przykładzie główna nazwa elementu EmailTagHelper to adres e-mail, więc <email> tag będzie przeznaczony dla użytkownika. Ta konwencja nazewnictwa powinna działać dla większości pomocników tagów. Później pokażę, jak ją zastąpić.

    • Klasa EmailTagHelper pochodzi z klasy TagHelper. Klasa TagHelper udostępnia metody i właściwości do pisania pomocników tagów.

    • Przesłonięć Process metodę steruje tym, co robi pomocnik tagu podczas wykonywania. Klasa TagHelper udostępnia również wersję asynchroniczną (ProcessAsync) z tymi samymi parametrami.

    • Parametr kontekstu do Process (i ProcessAsync) zawiera informacje skojarzone z wykonaniem bieżącego tagu HTML.

    • Parametr wyjściowy do Process (i ProcessAsync) zawiera stanowy element HTML reprezentatywny dla oryginalnego źródła używanego do generowania tagu HTML i zawartości.

    • Nasza nazwa klasy ma sufiks TagHelper, który nie jest wymagany, ale jest uważany za konwencję najlepszych rozwiązań. Klasę można zadeklarować jako:

    public class Email : TagHelper
    
  2. Aby udostępnić klasę EmailTagHelper wszystkim naszym Razor widokom, dodaj dyrektywę addTagHelper do Views/_ViewImports.cshtml pliku:

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

    Powyższy kod używa składni symboli wieloznacznych, aby określić wszystkie pomocniki tagów w naszym zestawie będą dostępne. Pierwszy ciąg po @addTagHelper określa pomocnik tagów do załadowania (użyj "*" dla wszystkich pomocników tagów), a drugi ciąg "AuthoringTagHelpers" określa zestaw, w których znajduje się pomocnik tagu. Należy również pamiętać, że drugi wiersz wprowadza pomocników tagów ASP.NET Core MVC przy użyciu składni symboli wieloznacznych (te pomocniki zostały omówione w temacie Wprowadzenie do pomocników tagów). @addTagHelper Jest to dyrektywa, która sprawia, że pomocnik tagów Razor jest dostępny dla widoku. Alternatywnie można podać w pełni kwalifikowaną nazwę (FQN) pomocnika tagu, jak pokazano poniżej:

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

Aby dodać pomocnika tagów do widoku przy użyciu nazwy FQN, najpierw dodaj nazwę FQN (AuthoringTagHelpers.TagHelpers.EmailTagHelper), a następnie nazwę zestawu (AuthoringTagHelpers, niekoniecznie namespace). Większość deweloperów woli używać składni symboli wieloznacznych. Wprowadzenie do pomocników tagów zawiera szczegółowe informacje na temat dodawania, usuwania, hierarchii i składni symboli wieloznacznych.

  1. Zaktualizuj znaczniki w Views/Home/Contact.cshtml pliku, wykonując następujące zmiany:

    @{
        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. Uruchom aplikację i użyj ulubionej przeglądarki, aby wyświetlić źródło HTML, aby sprawdzić, czy tagi poczty e-mail zostały zastąpione znacznikami zakotwiczenia (na przykład <a>Support</a>). Obsługa i marketing są renderowane jako linki, ale nie mają atrybutu umożliwiającego href ich działanie. Naprawimy to w następnej sekcji.

SetAttribute i SetContent

W tej sekcji zaktualizujemy EmailTagHelper element , aby utworzyć prawidłowy tag kotwicy dla wiadomości e-mail. Zaktualizujemy je, aby pobrać informacje z Razor widoku (w postaci atrybutu mail-to ) i użyć ich podczas generowania kotwicy.

Zaktualizuj klasę EmailTagHelper przy użyciu następujących elementów:

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-cased klasy i nazwy właściwości pomocników tagów są tłumaczone na ich przypadek kebab. W związku z tym, aby użyć atrybutu MailTo , należy użyć <email mail-to="value"/> odpowiednika.

  • Ostatni wiersz ustawia ukończoną zawartość dla naszego pomocnika tagów minimalnej funkcjonalności.

  • Wyróżniony wiersz przedstawia składnię dodawania atrybutów:

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

To podejście działa dla atrybutu "href", o ile nie istnieje obecnie w kolekcji atrybutów. Możesz również użyć output.Attributes.Add metody , aby dodać atrybut pomocnika tagu na końcu kolekcji atrybutów tagu.

  1. Zaktualizuj znaczniki w Views/Home/Contact.cshtml pliku, wykonując następujące zmiany:

    @{
        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. Uruchom aplikację i sprawdź, czy generuje poprawne linki.

Uwaga

Jeśli chcesz napisać tag wiadomości e-mail samodzielnie zamykający (<email mail-to="Rick" />), ostateczne dane wyjściowe będą również zamykane samodzielnie. Aby umożliwić pisanie tagu tylko za pomocą tagu startowego (<email mail-to="Rick">), należy oznaczyć klasę następującymi elementami:

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

W przypadku pomocnika samodzielnego tagu wiadomości e-mail dane wyjściowe to <a href="mailto:Rick@contoso.com" />. Tagi zakotwiczenia samodzielnego nie są prawidłowym kodem HTML, więc nie chcesz ich tworzyć, ale warto utworzyć pomocnika tagów, który jest zamykający. Pomocnicy tagów ustawiają typ TagMode właściwości po odczytaniu tagu.

Możesz również zamapować inną nazwę atrybutu na właściwość przy użyciu atrybutu [HtmlAttributeName].

Aby zamapować atrybut o nazwie recipient na MailTo właściwość:

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

Pomocnik tagu dla atrybutu recipient :

<email recipient="…"/>

Processasync

W tej sekcji napiszemy asynchroniczną pomocnik poczty e-mail.

  1. Zastąp klasę EmailTagHelper następującym kodem:

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

    Uwagi:

    • Ta wersja używa metody asynchronicznej ProcessAsync . Asynchroniczny GetChildContentAsync zwraca element Task zawierający element TagHelperContent.

    • Użyj parametru , output aby uzyskać zawartość elementu HTML.

  2. Wprowadź następującą zmianę w Views/Home/Contact.cshtml pliku, aby pomocnik tagu mógł uzyskać docelową wiadomość e-mail.

    @{
        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. Uruchom aplikację i sprawdź, czy generuje prawidłowe linki e-mail.

RemoveAll, PreContent.SetHtmlContent i PostContent.SetHtmlContent

  1. Dodaj następującą BoldTagHelper klasę do folderu 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>");
            }
        }
    }
    
    • Atrybut [HtmlTargetElement] przekazuje parametr atrybutu, który określa, że dowolny element HTML zawierający atrybut HTML o nazwie "bold" będzie zgodny, a Process metoda zastąpienia w klasie zostanie uruchomiona. W naszym przykładzie Process metoda usuwa atrybut "bold" (pogrubienie) i otacza element zawierający znaczniki .<strong></strong>

    • Ponieważ nie chcesz zastępować istniejącej zawartości tagu, musisz napisać tag PreContent.SetHtmlContent otwierający <strong> metodą i tag zamykający </strong> metodą PostContent.SetHtmlContent .

  2. Zmodyfikuj widok tak About.cshtml , aby zawierał wartość atrybutu bold . Ukończony kod jest pokazany poniżej.

    @{
        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. Uruchom aplikację. Możesz użyć ulubionej przeglądarki, aby sprawdzić źródło i zweryfikować znaczniki.

    Powyższy [HtmlTargetElement] atrybut dotyczy tylko znaczników HTML, które udostępniają nazwę atrybutu "bold". Element <bold> nie został zmodyfikowany przez pomocnika tagów.

  4. Oznacz jako komentarz wiersz atrybutu [HtmlTargetElement] i domyślnie będzie to oznaczać tagi określania wartości docelowej <bold> , czyli znaczniki HTML formularza <bold>. Pamiętaj, że domyślna konwencja nazewnictwa będzie zgodna z nazwą klasy BoldTagHelper do <bold> tagów.

  5. Uruchom aplikację i sprawdź, <bold> czy tag jest przetwarzany przez pomocnika tagów.

Dekorowanie klasy z wieloma [HtmlTargetElement] atrybutami powoduje logiczne OR obiektów docelowych. Na przykład użycie poniższego kodu spowoduje dopasowanie pogrubionego tagu lub atrybutu pogrubionego.

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

Po dodaniu wielu atrybutów do tej samej instrukcji środowisko uruchomieniowe traktuje je jako logiczne i. Na przykład w poniższym kodzie element HTML musi mieć nazwę "bold" z atrybutem o nazwie "bold" (<bold bold />), aby był zgodny.

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

Możesz również użyć elementu [HtmlTargetElement] , aby zmienić nazwę elementu docelowego. Jeśli na przykład chcesz użyć tagów BoldTagHelper docelowych <MyBold> , użyj następującego atrybutu:

[HtmlTargetElement("MyBold")]

Przekazywanie modelu do pomocnika tagów

  1. Dodaj folder Models.

  2. Dodaj następującą WebsiteContext klasę do folderu 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. Dodaj następującą WebsiteInformationTagHelper klasę do folderu 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;
          }
       }
    }
    
    • Jak wspomniano wcześniej, pomocnicy tagów tłumaczą pascal-cased nazwy klas i właściwości języka C# dla pomocników tagów w przypadku kebab. W związku z tym, aby użyć elementu WebsiteInformationTagHelper w Razorpliku , napiszesz .<website-information />

    • Nie identyfikujesz jawnie elementu docelowego za pomocą atrybutu [HtmlTargetElement] , więc wartość domyślna będzie przeznaczona website-information . Jeśli zastosowano następujący atrybut (zwróć uwagę, że nie jest to przypadek kebab, ale pasuje do nazwy klasy):

    [HtmlTargetElement("WebsiteInformation")]
    

    Tag <website-information /> przypadku kebab nie pasuje. Jeśli chcesz użyć atrybutu [HtmlTargetElement] , użyj przypadku kebab, jak pokazano poniżej:

    [HtmlTargetElement("Website-Information")]
    
    • Elementy, które się zamykają, nie mają zawartości. W tym przykładzie Razor adiustacja będzie używać tagu samo zamykającego, ale pomocnik tagu utworzy element sekcji (który nie zamyka się samodzielnie i piszesz zawartość wewnątrz section elementu). W związku z tym należy ustawić wartość TagMode na wartość , aby StartTagAndEndTag zapisywać dane wyjściowe. Alternatywnie możesz oznaczyć jako komentarz ustawienie TagMode wiersza i zapisać znaczniki z tagiem zamykającym. (Przykładowy znacznik jest udostępniany w dalszej części tego samouczka).

    • Znak $ (dolara) w następującym wierszu używa ciągu interpolowanego:

    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    
  4. Dodaj następujący znacznik do About.cshtml widoku. Wyróżniony znacznik wyświetla informacje o witrynie internetowej.

    @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" />
    

    Uwaga

    W adiustacji Razor pokazanej poniżej:

    <website-information info="webContext" />
    

    Razor wie, że info atrybut jest klasą, a nie ciągiem i chcesz napisać kod języka C#. Każdy atrybut pomocnika tagów @ innych niż ciąg powinien być zapisywany bez znaku .

  5. Uruchom aplikację i przejdź do widoku Informacje, aby wyświetlić informacje o witrynie internetowej.

    Uwaga

    Możesz użyć następującego znacznika z tagiem zamykającym i usunąć wiersz z TagMode.StartTagAndEndTag w pomocniku tagu:

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

Pomocnik tagu warunku

Pomocnik tagu warunku renderuje dane wyjściowe po przekazaniu wartości true.

  1. Dodaj następującą ConditionTagHelper klasę do folderu 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. Zastąp zawartość Views/Home/Index.cshtml pliku następującym znacznikiem:

    @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. Zastąp metodę Index w kontrolerze Home następującym kodem:

    public IActionResult Index(bool approved = false)
    {
        return View(new WebsiteContext
        {
            Approved = approved,
            CopyrightYear = 2015,
            Version = new Version(1, 3, 3, 7),
            TagsToShow = 20
        });
    }
    
  4. Uruchom aplikację i przejdź do strony głównej. Znaczniki w warunkowym div nie zostaną renderowane. Dołącz ciąg ?approved=true zapytania do adresu URL (na przykład http://localhost:1235/Home/Index?approved=true). approved jest ustawiona na wartość true, a zostanie wyświetlony znacznik warunkowy.

Uwaga

Użyj operatora nameof, aby określić atrybut docelowy, zamiast określać ciąg tak jak w przypadku pomocnika pogrubienia tagów:

[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();
      }
   }
}

Operator nameof będzie chronić kod, jeśli kiedykolwiek zostanie refaktoryzowany (możemy zmienić nazwę na RedCondition).

Unikanie konfliktów pomocnika tagów

W tej sekcji napiszesz parę pomocników tagów automatycznego łączenia. Pierwszy zastąpi znaczniki zawierające adres URL rozpoczynający się od HTTP do tagu kotwicy HTML zawierającego ten sam adres URL (i w ten sposób zwraca link do adresu URL). Drugi zrobi to samo dla adresu URL rozpoczynającego się od WWW.

Ponieważ te dwie pomocniki są ściśle powiązane i można je refaktoryzują w przyszłości, zachowamy je w tym samym pliku.

  1. Dodaj następującą AutoLinkerHttpTagHelper klasę do folderu 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}
        }
    }
    

    Uwaga

    Klasa jest przeznaczona AutoLinkerHttpTagHelper dla p elementów docelowych i używa wyrażenia regularnego do utworzenia kotwicy.

  2. Dodaj następujący znacznik na końcu Views/Home/Contact.cshtml pliku:

    @{
        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. Uruchom aplikację i sprawdź, czy pomocnik tagu poprawnie renderuje kotwicę.

  4. Zaktualizuj klasę tak AutoLinker , aby zawierała AutoLinkerWwwTagHelper tekst www przekonwertowany na tag kotwicy zawierający również oryginalny tekst www. Zaktualizowany kod został wyróżniony poniżej:

        [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. Uruchom aplikację. Zwróć uwagę, że tekst www jest renderowany jako link, ale tekst HTTP nie jest. Jeśli umieścisz punkt przerwania w obu klasach, zobaczysz, że klasa pomocnika tagów HTTP jest uruchamiana jako pierwsza. Problem polega na tym, że dane wyjściowe pomocnika tagów są buforowane, a gdy pomocnik tagów WWW jest uruchamiany, zastępuje buforowane dane wyjściowe z pomocnika tagów HTTP. W dalszej części samouczka zobaczymy, jak kontrolować kolejność uruchamiania pomocników tagów. Naprawimy kod przy użyciu następujących elementów:

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

    Uwaga

    W pierwszej edycji pomocników tagów automatycznego łączenia uzyskasz zawartość obiektu docelowego z następującym kodem:

    var childContent = await output.GetChildContentAsync();
    

    Oznacza to, że wywołujesz GetChildContentAsync metodę przy użyciu TagHelperOutput metody przekazanej ProcessAsync . Jak wspomniano wcześniej, ponieważ dane wyjściowe są buforowane, ostatni pomocnik tagu do uruchomienia wygrywa. Rozwiązano ten problem z następującym kodem:

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

    Powyższy kod sprawdza, czy zawartość została zmodyfikowana, a jeśli została ona zmodyfikowana, pobiera zawartość z buforu wyjściowego.

  6. Uruchom aplikację i sprawdź, czy dwa linki działają zgodnie z oczekiwaniami. Chociaż może się wydawać, że nasz pomocnik tagów automatycznego konsolidatora jest poprawny i kompletny, ma subtelny problem. Jeśli pomocnik tagów WWW jest uruchamiany jako pierwszy, linki www nie będą poprawne. Zaktualizuj kod, dodając przeciążenie, Order aby kontrolować kolejność uruchamiania tagu. Właściwość Order określa kolejność wykonywania względem innych pomocników tagów przeznaczonych dla tego samego elementu. Domyślna wartość zamówienia to zero, a wystąpienia o niższych wartościach są wykonywane jako pierwsze.

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

    Powyższy kod gwarantuje, że pomocnik tagów HTTP jest uruchamiany przed pomocnikem tagów WWW. Zmień Order wartość na MaxValue i sprawdź, czy znacznik wygenerowany dla tagu WWW jest niepoprawny.

Inspekcja i pobieranie zawartości podrzędnej

Pomocnicy tagów udostępniają kilka właściwości do pobierania zawartości.

  • Wynik GetChildContentAsync można dołączyć do output.Content.
  • Możesz sprawdzić wynik polecenia za pomocą GetContentpolecenia GetChildContentAsync .
  • Jeśli zmodyfikujesz output.Contentelement , treść narzędzia TagHelper nie zostanie wykonana ani renderowana, chyba że wywołasz GetChildContentAsync metodę tak jak w naszym przykładzie automatycznego konsolidatora:
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}
    }
}
  • Wiele wywołań zwraca GetChildContentAsync tę samą wartość i nie wykonuje TagHelper ponownie treści, chyba że przekazano parametr false wskazujący, że nie używasz buforowanego wyniku.

Ładowanie zminimalizowanego widoku częściowego TagHelper

W środowiskach produkcyjnych wydajność można poprawić przez ładowanie minyfikowanych widoków częściowych. Aby skorzystać z z minyfikowanego widoku częściowego w środowisku produkcyjnym:

  • Utwórz/skonfiguruj proces wstępnej kompilacji, który minifiesuje widoki częściowe.
  • Użyj poniższego kodu, aby załadować minyfikowane częściowe widoki w środowiskach nieprogramowania.
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;
        }
    }