Erstellen von Taghilfsprogrammen in ASP.NET Core

Von Rick Anderson

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Erste Schritte mit Taghilfsprogrammen

Dieses Tutorial soll als Einführung in das Programmieren von Taghilfsprogrammen dienen. Im Artikel Introduction to Tag Helpers (Einführung in Taghilfsprogramme) werden die Vorteile von Taghilfsprogrammen beschrieben.

Bei einem Taghilfsprogramm handelt es sich um eine Klasse, die die ITagHelper-Schnittstelle implementiert. Wenn Sie hingegen ein Taghilfsprogramm erstellen, stellen Sie in der Regel eine Ableitung von TagHelper her, wodurch Sie auf die Process-Methode zugreifen können.

  1. Erstellen Sie ein neues ASP.NET Core-Projekt mit dem Namen AuthoringTagHelpers. Für dieses Projekt benötigen Sie keine Authentifizierung.

  2. Erstellen Sie einen Ordner mit dem Namen TagHelpers, in dem die Taghilfsprogramme gespeichert werden sollen. Dieser TagHelpers Ordner ist nicht zwingend erforderlich, allerdings handelt es sich dabei um eine praktische Konvention. Im Folgenden werden Beispiele zum Schreiben einfacher Taghilfsprogramme beschrieben.

Ein Taghilfsprogramm mit den mindestens erforderlichen Elementen

In diesem Beispiel wird erläutert, wie Sie ein Taghilfsprogramm schreiben, das ein Update für ein E-Mail-Tag ausführt. Beispiel:

<email>Support</email>

Der Server verwendet das Taghilfsprogramm für E-Mails, um dieses Markup in Folgendes zu konvertieren:

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

Dabei handelt es sich um ein Anchor-Tag, das daraus einen E-Mail-Link erstellt. Dieses Hilfsprogramm kann sich als nützlich erweisen, wenn Sie eine Blog-Engine schreiben und eine E-Mail an die Marketingabteilung, den Support oder andere Kontakte senden möchten, die alle derselben Domäne angehören.

  1. Fügen Sie dem Ordner TagHelpers die folgende EmailTagHelper-Klasse hinzu.

    
    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
            }
        }
    }
    
    • Taghilfsprogramme verwenden Namenskonventionen, die auf die Elemente des Stammklassennamens ausgerichtet sind. Das Element TagHelper ist in dem Klassennamen allerdings nicht enthalten. In diesem Beispiel lautet der Stammname von EmailTagHelperemail, damit das <email>-Tag als Ziel verwendet wird. Diese Namenskonvention sollte für die meisten Taghilfsprogramme funktionieren. Nachfolgend finden Sie eine Erläuterung dazu, wie Sie diese außer Kraft setzen.

    • Die EmailTagHelper-Klasse wird von TagHelper abgeleitet. Über die TagHelper-Klasse werden Methoden und Eigenschaften für das Schreiben von Taghilfsprogrammen bereitgestellt.

    • Die überschriebene Process-Methode steuert die Funktionen des Taghilfsprogramms bei der Ausführung. Außerdem stellt die TagHelper-Klasse eine asynchrone Version (ProcessAsync) mit denselben Parametern bereit.

    • Der Kontextparameter von Process (und ProcessAsync) enthält Informationen, die der Ausführung des aktuellen HTML-Tags zugewiesen werden.

    • Der Ausgabeparameter von Process (und ProcessAsync) enthält ein zustandsbehaftetes HTML-Element, das für die Originalquelle steht, die zum Generieren eines HTML-Tags und von Inhalten verwendet wird.

    • Der Klassenname in diesem Beispiel enthält ein TagHelper-Suffix, das nicht erforderlich ist, aber als bewährter Bestandteil angesehen wird. Sie können die Klasse wie folgt deklarieren:

    public class Email : TagHelper
    
  2. Fügen Sie der Datei Views/_ViewImports.cshtml die addTagHelper-Anweisung hinzu, um die EmailTagHelper-Klasse für sämtliche Razor-Ansichten verfügbar zu machen:

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

    Im obenstehenden Code wird die Platzhaltersyntax verwendet, um alle Taghilfsprogramme anzugeben, die in der Assembly verfügbar sein sollen. In der ersten Zeichenfolge nach @addTagHelper wird angegeben, welches Taghilfsprogramm geladen werden soll (Verwenden Sie für alle Taghilfsprogramme „*“), und die zweite Zeichenfolge „AuthoringTagHelpers“ gibt die Assembly an, in der sich das Taghilfsprogramm befindet. Beachten Sie auch, dass die zweite Zeile die ASP.NET Core MVC-Taghilfsprogramme mit der Platzhaltersyntax einfügt (diese Hilfsprogramme werden in Einführung in Taghilfsprogramme behandelt). Es ist die @addTagHelper-Anweisung, die das Taghilfsprogramme für die Razor-Ansicht verfügbar macht. Stattdessen können Sie auch wie folgt den vollqualifizierten Namen eines Taghilfsprogramms eingeben:

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

Wenn Sie einer Ansicht über einen vollqualifizierten Namen ein Taghilfsprogramm hinzufügen möchten, müssen Sie zunächst den Namen (AuthoringTagHelpers.TagHelpers.EmailTagHelper) und dann den Assemblynamen (AuthoringTagHelpers, nicht notwendigerweise namespace) hinzufügen. Die meisten Entwickler verwenden am liebsten die Platzhaltersyntax. Unter Introduction to Tag Helpers (Einführung in Taghilfsprogramme) finden Sie mehr Details zum Hinzufügen und Entfernen von Taghilfsprogrammen, zur Hierarchie und zur Platzhaltersyntax.

  1. Aktualisieren Sie das Markup in der Datei Views/Home/Contact.cshtml mit diesen Änderungen:

    @{
        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. Führen Sie die App aus, und verwenden Sie einen beliebigen Browser, um die HTML-Quelle abzurufen, damit Sie überprüfen können, ob die E-Mail-Tags durch Anchor-Markups wie <a>Support</a> ersetzt wurden. Support und Marketing werden als Links gerendert. Allerdings besitzen sie kein href-Attribut, das sie funktionsfähig macht. Dies soll im nächsten Abschnitt behoben werden.

„SetAttribute“ und „SetContent“

In diesem Abschnitt wird erläutert, wie Sie ein Update für EmailTagHelper ausführen, sodass ein gültiges Anchor-Tag für die E-Mail erstellt wird. Für das Hilfsprogramm soll ein Update ausgeführt werden, damit es der Razor-Ansicht Informationen in Form eines mail-to-Attributs entnehmen und dieses zum Generieren des Ankers verwenden kann.

Führen Sie über folgenden Code ein Update für die EmailTagHelper-Klasse aus:

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);
    }
}
  • Namen von Klassen und Eigenschaften für Taghilfsprogramme, die in Pascal-Schreibweise angegeben sind, werden in Kebab-Schreibweise übersetzt. Wenn Sie daher das MailTo-Attribut verwenden möchten, müssen Sie das entsprechende <email mail-to="value"/>-Äquivalent auswählen.

  • Mit der letzten Zeile wird der Inhalt dieses Taghilfsprogramms fertig gestellt, das alle mindestens erforderlichen Elemente enthält.

  • In der markierten Zeile wird die Syntax zum Hinzufügen von Attributen dargestellt:

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

Dieser Ansatz funktioniert für das Attribut „href“, wenn es zu diesem Zeitpunkt noch nicht in der Attributsammlung enthalten ist. Außerdem können Sie die output.Attributes.Add-Methode verwenden, um ein Attribut des Taghilfsprogramms am Ende der Tagattributsammlung hinzuzufügen.

  1. Aktualisieren Sie das Markup in der Datei Views/Home/Contact.cshtml mit diesen Änderungen:

    @{
        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. Führen Sie die App aus, und überprüfen Sie, ob die richtigen Links generiert werden.

Hinweis

Wenn das E-Mail-Tag selbstschließend sein soll (<email mail-to="Rick" />), ist auch die endgültige Ausgabe selbstschließend. Um die Funktion zum Schreiben des Tags nur mit einem Starttag (<email mail-to="Rick">) zu aktivieren, müssen Sie die Klasse wie folgt markieren:

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

Bei einem selbstschließenden E-Mail-Taghilfsprogramm sieht die Ausgabe wie folgt aus <a href="mailto:Rick@contoso.com" />. Bei selbstschließenden Anchor-Tags handelt es sich nicht um gültige HTML-Elemente. Daher sollten Sie diese nicht erstellen. Erstellen Sie stattdessen ein selbstschließendes Taghilfsprogramm. Taghilfsprogramme legen den Typ der TagMode-Eigenschaft fest, nachdem ein Tag gelesen wurde.

Sie können einer Eigenschaft auch mithilfe des [HtmlAttributeName]-Attributs einen anderen Attributnamen zuordnen.

So ordnen Sie der MailTo-Eigenschaft ein Attribut namens recipient zu:

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

Taghilfsprogramm für das recipient-Attribut:

<email recipient="…"/>

ProcessAsync

In diesem Abschnitt wird beschrieben, wie Sie ein asynchrones E-Mail-Hilfsprogramm schreiben.

  1. Ersetzen Sie die Klasse EmailTagHelper durch den folgenden Code:

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

    Hinweise:

    • Diese Version verwendet die asynchrone ProcessAsync-Methode. Die asynchrone GetChildContentAsync-Methode gibt Task mit TagHelperContent zurück.

    • Verwenden Sie den Parameter output, um Inhalte des HTML-Elements abzurufen.

  2. Nehmen Sie folgende Änderung an der Datei Views/Home/Contact.cshtml vor, damit das Taghilfsprogramm die Ziel-E-Mail abrufen kann.

    @{
        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. Führen Sie die App aus, und überprüfen Sie, ob gültige E-Mail-Links generiert werden.

„RemoveAll“, „PreContent.SetHtmlContent“ und „PostContent.SetHtmlContent“

  1. Fügen Sie dem Ordner TagHelpers die folgende BoldTagHelper-Klasse hinzu.

    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>");
            }
        }
    }
    
    • Das [HtmlTargetElement]-Attribut übergibt einen Attributparameter, der angibt, dass diesem ein HTML-Element mit dem HTML-Attribut „bold“ zugeordnet werden kann. Anschließend wird die Überschreibungsmethode Process in der Klasse ausgeführt. In diesem Beispiel entfernt die Methode Process das Attribut „bold“ und umschließt das enthaltene Markup mit <strong></strong>.

    • Da der bestehende Taginhalt nicht ersetzt werden soll, müssen Sie das Starttag <strong> über die Methode PreContent.SetHtmlContent und das Endtag </strong> über die Methode PostContent.SetHtmlContent schreiben.

  2. Ändern Sie die Ansicht About.cshtml, damit diese den Attributwert bold enthält. Der fertige Code wird nachfolgend dargestellt.

    @{
        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. Führen Sie die App aus. Sie können einen beliebigen Browser verwenden, um die Quelle zu untersuchen und das Markup zu überprüfen.

    Das oben genannte [HtmlTargetElement]-Attribut gilt nur für HTML-Markups mit dem Attributnamen „bold“. Das <bold>-Element wurde vom Taghilfsprogramm nicht verändert.

  4. Kommentieren Sie die Attributzeile [HtmlTargetElement] aus, damit standardmäßig <bold>-Tags angezielt werden, also HTML-Markups im Format <bold>. Beachten Sie, dass die Standardnamenskonvention dem Klassennamen BoldTagHelper den <bold>-Tags entspricht.

  5. Führen Sie die App aus, und überprüfen Sie, ob das <bold>-Tag vom Taghilfsprogramm verarbeitet wird.

Wenn Sie eine Klasse durch mehrere [HtmlTargetElement]-Attribute ergänzen, wird ein logischer ODER-Operator der Ziele erstellt. Wenn Sie z.B. den nachfolgenden Code verwenden, wird ein „bold“-Tag oder ein „bold“-Attribut zugeordnet.

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

Wenn mehrere Attribute derselben Anweisung hinzugefügt werden, behandelt die Runtime diese als logisches UND. Beispielsweise muss im nachfolgenden Code ein HTML-Element den Namen „bold“ mit einem Attribut namens „bold“ (<bold bold />) enthalten sein, damit dieses zugeordnet werden kann.

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

Außerdem können Sie [HtmlTargetElement] verwenden, um den Namen des angezielten Elements zu ändern. Wenn Sie z.B. möchten, dass BoldTagHelper<MyBold>-Tags anzielt, müssen Sie die folgenden Attribute verwenden:

[HtmlTargetElement("MyBold")]

Übergeben eines Modells an das Taghilfsprogramm

  1. Fügen Sie einen Models-Ordner hinzu.

  2. Fügen Sie dem Ordner Models die folgende WebsiteContext-Klasse hinzu:

    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. Fügen Sie dem Ordner TagHelpers die folgende WebsiteInformationTagHelper-Klasse hinzu.

    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;
          }
       }
    }
    
    • Wie obenstehend erwähnt, übersetzen Taghilfsprogramme C#-Klassennamen und -Eigenschaften in der Pascal-Schreibweise für Taghilfsprogramme in Kebab-Schreibweise. Wenn Sie WebsiteInformationTagHelper in Razor verwenden möchten, schreiben Sie <website-information />.

    • Das Zielelement wird mit dem [HtmlTargetElement]-Attribut nicht explizit identifiziert, sodass standardmäßig website-information angezielt wird. Wenn Sie das folgende Attribut angewendet haben (beachten Sie, dass es sich hierbei nicht um Kebab Case handelt, sondern das Attribut dem Klassennamen zugeordnet wird):

    [HtmlTargetElement("WebsiteInformation")]
    

    Das Tag <website-information /> in Kebab-Schreibweise wird dann nicht zugeordnet. Wenn Sie das [HtmlTargetElement]-Attribut verwenden, müssen Sie wie nachfolgend dargestellt Kebab Case verwenden:

    [HtmlTargetElement("Website-Information")]
    
    • Selbstschließende Elemente haben keinen Inhalt. In diesem Beispiel verwendet das Razor-Markup ein selbstschließendes Tag, aber das Taghilfsprogramm erstellt ein section-Element. Dieses ist nicht selbstschließend, und Sie können Inhalt in das section-Element schreiben. Aus diesem Grund müssen Sie TagMode auf StartTagAndEndTag festlegen, um Ausgaben zu schreiben. Stattdessen können Sie auch die Zeileneinstellung TagMode auskommentieren und Markups mit einem Endtag schreiben. (Ein Beispielmarkup wird in einem nachfolgenden Abschnitt dieses Tutorials zur Verfügung gestellt.)

    • Das Dollarzeichen ($) in der folgenden Zeile verwendet eine interpolierte Zeichenfolge:

    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    
  4. Fügen Sie das folgende Markup am Ende der About.cshtml-Ansicht hinzu. Das markierte Markup zeigt die Websiteinformationen an.

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

    Hinweis

    Im nachfolgenden Razor-Markup:

    <website-information info="webContext" />
    

    Razor weiß, dass es sich bei dem info-Attribut um eine Klasse und nicht um eine Zeichenfolge handelt und Sie C#-Code schreiben möchten. Alle Attribute von Taghilfsprogrammen, die keine Zeichenfolgen darstellen, sollten ohne das Zeichen @ geschrieben werden.

  5. Führen Sie die App aus, und navigieren Sie zur Ansicht „Info“, um die Websiteinformationen zu sehen.

    Hinweis

    Sie können das folgende Markup mit dem Endtag verwenden und die Zeile mit TagMode.StartTagAndEndTag aus dem Taghilfsprogramm entfernen:

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

Taghilfsprogramm für Bedingungen

Das Taghilfsprogramm für Bedingungen rendert Ausgaben, wenn ein TRUE-Wert zurückgegeben wird.

  1. Fügen Sie dem Ordner TagHelpers die folgende ConditionTagHelper-Klasse hinzu.

    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. Ersetzen Sie den Inhalt der Datei Views/Home/Index.cshtml durch folgendes Markup:

    @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. Ersetzen Sie die Index-Methode im Home-Controller durch den folgenden Code:

    public IActionResult Index(bool approved = false)
    {
        return View(new WebsiteContext
        {
            Approved = approved,
            CopyrightYear = 2015,
            Version = new Version(1, 3, 3, 7),
            TagsToShow = 20
        });
    }
    
  4. Führen Sie die App aus, und navigieren Sie zur Homepage. Das Markup im bedingten div-Element wird nicht gerendert. Fügen Sie die Abfragezeichenfolge ?approved=true an die URL an (z.B. http://localhost:1235/Home/Index?approved=true). approved ist auf TRUE festgelegt, und das bedingte Markup wird angezeigt.

Hinweis

Verwenden Sie den nameof-Operator, um das anzuzielende Attribut wie beim „bold“-Taghilfsprogramm anzugeben, anstatt eine Zeichenfolge anzugeben:

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

Der nameof-Operator schützt den Code, wenn dieser umgestaltet wird, also wenn z.B. der Name in RedCondition geändert wird.

Vermeiden von Konflikten mit dem Taghilfsprogramm

In diesem Abschnitt wird erläutert, wie Sie zwei Taghilfsprogramme für automatische Verlinkungen schreiben. Das erste ersetzt Markups mit einer URL, die mit HTTP beginnt, durch ein HTML-Anchor-Tag mit derselben URL, sodass ein Link zur der URL zurückgegeben wird. Das zweite führt dieselbe Aktion aus, allerdings für URLs, die mit WWW beginnen.

Da dieses beiden Hilfsprogramme sehr ähnlich funktionieren und Sie sie möglicherweise in der Zukunft umgestalten möchten, werden diese in derselben Datei gespeichert.

  1. Fügen Sie dem Ordner TagHelpers die folgende AutoLinkerHttpTagHelper-Klasse hinzu.

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

    Hinweis

    Die AutoLinkerHttpTagHelper-Klasse zielt p-Elemente an und verwendet RegEx, um den Anchor zu erstellen.

  2. Fügen Sie am Ende der Datei Views/Home/Contact.cshtml das folgende Markup hinzu:

    @{
        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. Führen Sie die App aus, und überprüfen Sie, ob das Taghilfsprogramm den Anchor richtig rendert.

  4. Führen Sie ein Update für die AutoLinker-Klasse aus, um AutoLinkerWwwTagHelper einzufügen, wodurch WWW-Text in ein Anchor-Tag konvertiert wird, das ebenfalls den ursprünglichen WWW-Text enthält. Der aktualisierte Code wird im folgenden Beispiel markiert:

        [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. Führen Sie die App aus. Beachten Sie, dass der WWW-Text als Link gerendert wird, der HTTP-Text hingegen nicht. Wenn Sie in beide Klassen einen Haltepunkt einfügen, wird die HTTP-Hilfsprogrammklasse zuerst ausgeführt. Das Problem dabei ist, dass die Ausgabe des Taghilfsprogramms zwischengespeichert wird, und wenn das WWW-Hilfsprogramm ausgeführt wird, wird die zwischengespeicherte Ausgabe des HTTP-Hilfsprogramms überschrieben. Nachfolgend wird erläutert, wie Sie die Reihenfolge kontrollieren, in der Taghilfsprogramme ausgeführt werden. Codefehler werden wie folgt behoben:

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

    Hinweis

    In der ersten Version der Taghilfsprogramme für automatische Verlinkungen konnten Sie den Inhalt des Ziels über folgenden Code abrufen:

    var childContent = await output.GetChildContentAsync();
    

    Das bedeutet, Sie rufen GetChildContentAsync über das TagHelperOutput-Objekt ab, das in der ProcessAsync-Methode übergeben wurde. Wie zuvor bereits erwähnt, gewinnt das letzte Taghilfsprogramm, das ausgeführt wird, da die Ausgabe zwischengespeichert wird. Sie haben dieses Problem mithilfe des folgenden Codes behoben:

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

    Der obenstehende Code prüft, ob der Inhalt verändert wurde. Wenn das der Fall ist, ruft er den Inhalt vom Ausgabepuffer ab.

  6. Führen Sie die App aus, und überprüfen Sie, ob die beiden Links wie gewünscht funktionieren. Dabei kann es oft sein, dass es scheint, als würde das Taghilfsprogramm für die automatische Verlinkung einwandfrei funktionieren, obwohl ein verstecktes Problem besteht. Wenn das WWW-Taghilfsprogramm zuerst ausgeführt wird, werden die WWW-Links fehlerhaft erstellt. Aktualisieren Sie den Code, indem Sie die Überladung Order hinzufügen, um die Reihenfolge zu kontrollieren, in der das Tag ausgeführt wird. Die Eigenschaft Order bestimmt die Ausführungsreihenfolge, die im Zusammenhang mit anderen Taghilfsprogrammen steht, die auf dasselbe Element ausgerichtet sind. Der Wert der Standardreihenfolge ist 0 (null), und Instanzen mit niedrigeren Werten werden zuerst ausgeführt.

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

    Mit dem vorhergehenden Code wird sichergestellt, dass das HTTP-Taghilfsprogramm vor dem WWW-Taghilfsprogramm ausgeführt wird. Ändern Sie Order in MaxValue, und überprüfen Sie, ob das für das WWW-Tag generierte Markup falsch ist.

Überprüfen und Abrufen von untergeordnetem Inhalt

Die Taghilfsprogramme stellen mehrere Eigenschaften zum Abrufen von Inhalt zur Verfügung.

  • Das Ergebnis von GetChildContentAsync kann an output.Content angefügt werden.
  • Sie können das Ergebnis von GetChildContentAsync mit GetContent prüfen.
  • Wenn Sie output.Content ändern, wird der TagHelper-Text nicht ausgeführt oder gerendert, solange Sie nicht wie im Beispiel zur automatischen Verlinkung GetChildContentAsync aufrufen:
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}
    }
}
  • Bei mehreren Aufrufen von GetChildContentAsync wird derselbe Wert zurückgegeben, und der TagHelper-Text wird nicht erneut ausgeführt, solange Sie keinen FALSE-Parameter übergeben, der darauf hindeutet, dass die zwischengespeicherten Ergebnisse nicht verwendet werden sollen.

TagHelper für das Laden minimierter Teilansichten

In Produktionsumgebungen lässt sich die Leistung steigern, indem minimierte Teilansichten geladen werden. Um von minimierten Teilansichten in der Produktion zu profitieren, gehen Sie folgendermaßen vor:

  • Erstellen Sie einen Präbuildprozess, der Teilansichten minimiert, und richten Sie den Prozess ein.
  • Verwenden Sie den folgenden Code, um minimierte Teilansichten in Nicht-Entwicklungsumgebungen zu laden.
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;
        }
    }