Créer des Tag Helpers dans ASP.NET CoreAuthor Tag Helpers in ASP.NET Core

De Rick AndersonBy Rick Anderson

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)View or download sample code (how to download)

Bien démarrer avec les Tag HelpersGet started with Tag Helpers

Ce didacticiel fournit une introduction à la programmation des Tag Helpers.This tutorial provides an introduction to programming Tag Helpers. Introduction aux Tag Helpers décrit les avantages offerts par les Tag Helpers.Introduction to Tag Helpers describes the benefits that Tag Helpers provide.

Un Tag Helper est toute classe qui implémente l’interface ITagHelper.A tag helper is any class that implements the ITagHelper interface. Toutefois, quand vous créez un Tag Helper, vous dérivez généralement de TagHelper, ce qui vous permet d’accéder à la méthode Process.However, when you author a tag helper, you generally derive from TagHelper, doing so gives you access to the Process method.

  1. Créez un projet ASP.NET Core nommé AuthoringTagHelpers.Create a new ASP.NET Core project called AuthoringTagHelpers. Vous n’aurez pas besoin d’authentification pour ce projet.You won't need authentication for this project.

  2. Créez un dossier pour stocker les Tag Helpers appelé TagHelpers.Create a folder to hold the Tag Helpers called TagHelpers. Le dossier TagHelpers n’est pas obligatoire, mais il est judicieux de le créer.The TagHelpers folder is not required, but it's a reasonable convention. Commençons à présent à écrire quelques Tag Helpers simples.Now let's get started writing some simple tag helpers.

Tag Helper minimalA minimal Tag Helper

Dans cette section, vous écrivez un Tag Helper qui met à jour une balise e-mail.In this section, you write a tag helper that updates an email tag. Par exemple :For example:

<email>Support</email>

Le serveur utilise notre Tag Helper e-mail pour convertir ce balisage en code suivant :The server will use our email tag helper to convert that markup into the following:

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

Autrement dit, une balise d’ancrage qui en fait un lien e-mail.That is, an anchor tag that makes this an email link. Vous pouvez effectuer cette opération si vous écrivez un moteur de blog qui doit envoyer des e-mails pour le marketing, le support et d’autres contacts, tous dans le même domaine.You might want to do this if you are writing a blog engine and need it to send email for marketing, support, and other contacts, all to the same domain.

  1. Ajoutez la classe EmailTagHelper suivante au dossier TagHelpers.Add the following EmailTagHelper class to the TagHelpers folder.

    
    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
            }
        }
    }
    
    • Les Tag Helpers utilisent une convention de nommage qui cible des éléments du nom de classe racine (moins la partie TagHelper du nom de classe).Tag helpers use a naming convention that targets elements of the root class name (minus the TagHelper portion of the class name). Dans cet exemple, comme le nom racine de EmailTagHelper est email, la balise <email> est ciblée.In this example, the root name of EmailTagHelper is email, so the <email> tag will be targeted. Cette convention de nommage doit fonctionner pour la plupart des Tag Helpers et je vous montrerai plus tard comment la remplacer.This naming convention should work for most tag helpers, later on I'll show how to override it.

    • La classe EmailTagHelper dérive de la classe TagHelper.The EmailTagHelper class derives from TagHelper. La classe TagHelper fournit des méthodes et propriétés pour l’écriture des Tag Helpers.The TagHelper class provides methods and properties for writing Tag Helpers.

    • La méthode Process substituée contrôle ce que fait le Tag Helper lors de son exécution.The overridden Process method controls what the tag helper does when executed. La classe TagHelper fournit également une version asynchrone (ProcessAsync) avec les mêmes paramètres.The TagHelper class also provides an asynchronous version (ProcessAsync) with the same parameters.

    • Le paramètre de contexte pour Process (et ProcessAsync) contient des informations associées à l’exécution de la balise HTML actuelle.The context parameter to Process (and ProcessAsync) contains information associated with the execution of the current HTML tag.

    • Le paramètre de sortie pour Process (et ProcessAsync) contient un élément HTML avec état représentatif de la source d’origine utilisée pour générer une balise HTML et le contenu.The output parameter to Process (and ProcessAsync) contains a stateful HTML element representative of the original source used to generate an HTML tag and content.

    • Le nom de notre classe comporte un suffixe TagHelper, ce qui n’est pas obligatoire, mais est considéré comme une bonne pratique.Our class name has a suffix of TagHelper, which is not required, but it's considered a best practice convention. Vous pouvez déclarer la classe comme suit :You could declare the class as:

    public class Email : TagHelper
    
  2. Afin de rendre la classe EmailTagHelper disponible pour toutes les vues Razor, ajoutez la directive addTagHelper au fichier Views/_ViewImports.cshtml :To make the EmailTagHelper class available to all our Razor views, add the addTagHelper directive to the Views/_ViewImports.cshtml file:

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

    Le code ci-dessus utilise la syntaxe d’expressions génériques pour spécifier que tous les Tag Helpers dans notre assembly seront disponibles.The code above uses the wildcard syntax to specify all the tag helpers in our assembly will be available. La première chaîne après @addTagHelper désigne le Tag Helper à charger (utilisez « * » pour tous les Tag Helpers), et la deuxième chaîne « AuthoringTagHelpers » indique l’assembly dans lequel se trouve le Tag Helper.The first string after @addTagHelper specifies the tag helper to load (Use "*" for all tag helpers), and the second string "AuthoringTagHelpers" specifies the assembly the tag helper is in. En outre, Notez que la deuxième ligne insère les ASP.NET Core de balises MVC à l’aide de la syntaxe avec caractères génériques (ces informations sont présentées dans Introduction aux balises d’aide). Il s’agit de la directive @addTagHelper qui met le tag Helper à la disposition de la vue Razor.Also, note that the second line brings in the ASP.NET Core MVC tag helpers using the wildcard syntax (those helpers are discussed in Introduction to Tag Helpers.) It's the @addTagHelper directive that makes the tag helper available to the Razor view. Sinon, vous pouvez fournir le nom qualifié complet d’un Tag Helper comme indiqué ci-dessous :Alternatively, you can provide the fully qualified name (FQN) of a tag helper as shown below:

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

Pour ajouter un Tag Helper à une vue à l’aide d’un nom qualifié complet, ajoutez d’abord ce nom (AuthoringTagHelpers.TagHelpers.EmailTagHelper), puis le nom d’assembly (AuthoringTagHelpers, pas nécessairement namespace).To add a tag helper to a view using a FQN, you first add the FQN (AuthoringTagHelpers.TagHelpers.EmailTagHelper), and then the assembly name (AuthoringTagHelpers, not necessarily the namespace). La plupart des développeurs préfèrent utiliser la syntaxe d’expressions génériques.Most developers will prefer to use the wildcard syntax. Introduction aux Tag Helpers décrit en détail l’ajout et la suppression de Tag Helpers, la hiérarchie et la syntaxe d’expressions génériques.Introduction to Tag Helpers goes into detail on tag helper adding, removing, hierarchy, and wildcard syntax.

  1. Mettez à jour le balisage dans le fichier Views/Home/Contact.cshtml avec les modifications suivantes :Update the markup in the Views/Home/Contact.cshtml file with these changes:

    @{
        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. Exécutez l’application et utilisez votre navigateur favori pour afficher la source HTML afin de vérifier que les balises e-mail sont remplacées par un balisage d’ancrage (par exemple, <a>Support</a>).Run the app and use your favorite browser to view the HTML source so you can verify that the email tags are replaced with anchor markup (For example, <a>Support</a>). Support et Marketing s’affichent sous forme de liens, mais sans l’attribut href pour les rendre fonctionnels.Support and Marketing are rendered as a links, but they don't have an href attribute to make them functional. Nous le corrigerons dans la section suivante.We'll fix that in the next section.

SetAttribute et SetContentSetAttribute and SetContent

Dans cette section, nous allons mettre à jour la classe EmailTagHelper afin qu’elle crée une balise d’ancrage valide pour les e-mails.In this section, we'll update the EmailTagHelper so that it will create a valid anchor tag for email. Nous allons la mettre à jour pour extraire des informations d’une vue Razor (sous la forme d’un attribut mail-to) et les utiliser lors de la génération de l’ancre.We'll update it to take information from a Razor view (in the form of a mail-to attribute) and use that in generating the anchor.

Mettez à jour la classe EmailTagHelper avec le code suivant :Update the EmailTagHelper class with the following:

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);
    }
}
  • Les noms de propriété et de classe de casse Pascal pour les Tag Helpers sont convertis en casse kebab (mots séparés par des tirets).Pascal-cased class and property names for tag helpers are translated into their kebab case. Par conséquent, pour utiliser l’attribut MailTo, vous employez l’équivalent <email mail-to="value"/>.Therefore, to use the MailTo attribute, you'll use <email mail-to="value"/> equivalent.

  • La dernière ligne définit le contenu terminé pour notre Tag Helper fonctionnel au minimum.The last line sets the completed content for our minimally functional tag helper.

  • La ligne en surbrillance montre la syntaxe pour l’ajout d’attributs :The highlighted line shows the syntax for adding attributes:

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

Cette approche fonctionne pour l’attribut « href » tant qu’il n’existe pas dans la collection d’attributs.That approach works for the attribute "href" as long as it doesn't currently exist in the attributes collection. Vous pouvez également utiliser la méthode output.Attributes.Add pour ajouter un attribut de Tag Helper à la fin de la collection des attributs de balise.You can also use the output.Attributes.Add method to add a tag helper attribute to the end of the collection of tag attributes.

  1. Mettez à jour le balisage dans le fichier Views/Home/Contact.cshtml avec les modifications suivantes :Update the markup in the Views/Home/Contact.cshtml file with these changes:

    @{
        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. Exécutez l’application et vérifiez qu’elle génère les liens corrects.Run the app and verify that it generates the correct links.

Notes

Si vous deviez écrire la fermeture automatique de la balise e-mail (<email mail-to="Rick" />), la sortie finale se fermerait aussi automatiquement.If you were to write the email tag self-closing (<email mail-to="Rick" />), the final output would also be self-closing. Pour activer la possibilité d’écrire la balise avec uniquement une balise de début (<email mail-to="Rick">), vous devez marquer la classe avec ce qui suit :To enable the ability to write the tag with only a start tag (<email mail-to="Rick">) you must mark the class with the following:

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

Avec un Tag Helper e-mail de fermeture automatique, la sortie serait <a href="mailto:Rick@contoso.com" />.With a self-closing email tag helper, the output would be <a href="mailto:Rick@contoso.com" />. Comme les balises d’ancrage de fermeture automatique ne sont pas du code HTML valide, vous n’allez pas en créer, mais vous pouvez peut-être créer un Tag Helper qui se ferme automatiquement.Self-closing anchor tags are not valid HTML, so you wouldn't want to create one, but you might want to create a tag helper that's self-closing. Les Tag Helpers définissent le type de la propriété TagMode après la lecture d’une balise.Tag helpers set the type of the TagMode property after reading a tag.

ProcessAsyncProcessAsync

Dans cette section, nous allons écrire un Tag Helper e-mail asynchrone.In this section, we'll write an asynchronous email helper.

  1. Remplacez la classe EmailTagHelper par le code suivant :Replace the EmailTagHelper class with the following 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);
        }
    }
    

    Remarques :Notes:

    • Cette version utilise la méthode ProcessAsync asynchrone.This version uses the asynchronous ProcessAsync method. L’élément GetChildContentAsync asynchrone retourne un élément Task contenant TagHelperContent.The asynchronous GetChildContentAsync returns a Task containing the TagHelperContent.

    • Utilisez le paramètre output pour obtenir le contenu de l’élément HTML.Use the output parameter to get contents of the HTML element.

  2. Apportez la modification suivante au fichier Views/Home/Contact.cshtml pour que le Tag Helper puisse obtenir l’e-mail cible.Make the following change to the Views/Home/Contact.cshtml file so the tag helper can get the target email.

    @{
        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. Exécutez l’application et vérifiez qu’elle génère des liens e-mail valides.Run the app and verify that it generates valid email links.

RemoveAll, PreContent.SetHtmlContent et PostContent.SetHtmlContentRemoveAll, PreContent.SetHtmlContent and PostContent.SetHtmlContent

  1. Ajoutez la classe BoldTagHelper suivante au dossier TagHelpers.Add the following BoldTagHelper class to the TagHelpers folder.

    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>");
            }
        }
    }
    
    • L’attribut [HtmlTargetElement] passe un paramètre d’attribut qui spécifie qu’un élément HTML qui contient un attribut HTML nommé « bold » correspond, et la méthode override Process dans la classe s’exécute.The [HtmlTargetElement] attribute passes an attribute parameter that specifies that any HTML element that contains an HTML attribute named "bold" will match, and the Process override method in the class will run. Dans notre exemple, la méthode Process supprime l’attribut « bold » et entoure le balisage contenant avec <strong></strong>.In our sample, the Process method removes the "bold" attribute and surrounds the containing markup with <strong></strong>.

    • Comme vous ne voulez pas remplacer le contenu de la balise, vous devez écrire la balise <strong> d’ouverture avec la méthode PreContent.SetHtmlContent et la balise </strong> de fermeture avec la méthode PostContent.SetHtmlContent.Because you don't want to replace the existing tag content, you must write the opening <strong> tag with the PreContent.SetHtmlContent method and the closing </strong> tag with the PostContent.SetHtmlContent method.

  2. Modifiez la vue About.cshtml pour qu’elle contienne une valeur d’attribut bold.Modify the About.cshtml view to contain a bold attribute value. Le code terminé est indiqué ci-dessous.The completed code is shown below.

    @{
        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. Exécutez l'application.Run the app. Vous pouvez utiliser votre navigateur favori pour inspecter la source et vérifier le balisage.You can use your favorite browser to inspect the source and verify the markup.

    L’attribut [HtmlTargetElement] ci-dessus cible uniquement le balisage HTML qui fournit le nom d’attribut « bold ».The [HtmlTargetElement] attribute above only targets HTML markup that provides an attribute name of "bold". L’élément <bold> n’a pas été modifié par le Tag Helper.The <bold> element wasn't modified by the tag helper.

  4. Commentez la ligne de l’attribut [HtmlTargetElement] et il ciblera par défaut les balises <bold>, autrement dit le balisage HTML sous la forme <bold>.Comment out the [HtmlTargetElement] attribute line and it will default to targeting <bold> tags, that is, HTML markup of the form <bold>. Gardez à l’esprit que la convention de nommage par défaut associe le nom de classe BoldTagHelper aux balises <bold>.Remember, the default naming convention will match the class name BoldTagHelper to <bold> tags.

  5. Exécutez l’application et vérifiez que la balise <bold> est traitée par le Tag Helper.Run the app and verify that the <bold> tag is processed by the tag helper.

Le fait de décorer une classe avec plusieurs attributs [HtmlTargetElement] aboutit à une opération OR logique des cibles.Decorating a class with multiple [HtmlTargetElement] attributes results in a logical-OR of the targets. Par exemple, avec le code ci-dessous, une balise en gras ou un attribut gras correspondent.For example, using the code below, a bold tag or a bold attribute will match.

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

Quand plusieurs attributs sont ajoutés à la même instruction, le runtime les traite comme une opération AND logique.When multiple attributes are added to the same statement, the runtime treats them as a logical-AND. Par exemple, dans le code ci-dessous, un élément HTML doit être nommé « bold » avec un attribut nommé « bold » (<bold bold />) pour la mise en correspondance.For example, in the code below, an HTML element must be named "bold" with an attribute named "bold" (<bold bold />) to match.

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

Vous pouvez également utiliser l’attribut [HtmlTargetElement] pour modifier le nom de l’élément ciblé.You can also use the [HtmlTargetElement] to change the name of the targeted element. Par exemple, si vous souhaitez que BoldTagHelper cible les balises <MyBold>, vous utilisez l’attribut suivant :For example if you wanted the BoldTagHelper to target <MyBold> tags, you would use the following attribute:

[HtmlTargetElement("MyBold")]

Passer un modèle à un Tag HelperPass a model to a Tag Helper

  1. Ajoutez un dossier Models.Add a Models folder.

  2. Ajoutez la classe WebsiteContext suivante au dossier Models :Add the following WebsiteContext class to the Models folder:

    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. Ajoutez la classe WebsiteInformationTagHelper suivante au dossier TagHelpers.Add the following WebsiteInformationTagHelper class to the TagHelpers folder.

    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;
          }
       }
    }
    
    • Comme mentionné précédemment, les Tag Helpers convertissent les propriétés et noms de classe C# de casse Pascal en casse kebab (mots séparés par des tirets).As mentioned previously, tag helpers translates Pascal-cased C# class names and properties for tag helpers into kebab case. Par conséquent, pour utiliser la classe WebsiteInformationTagHelper dans Razor, vous allez écrire <website-information />.Therefore, to use the WebsiteInformationTagHelper in Razor, you'll write <website-information />.

    • Comme vous n’identifiez pas de manière explicite l’élément cible avec l’attribut [HtmlTargetElement], la valeur par défaut de website-information est ciblée.You are not explicitly identifying the target element with the [HtmlTargetElement] attribute, so the default of website-information will be targeted. Si vous avez appliqué l’attribut suivant (notez que la casse n’est pas kebab, mais il correspond au nom de la classe) :If you applied the following attribute (note it's not kebab case but matches the class name):

    [HtmlTargetElement("WebsiteInformation")]
    

    La balise en casse kebab <website-information /> ne correspond pas.The kebab case tag <website-information /> wouldn't match. Si vous voulez utiliser l’attribut [HtmlTargetElement], vous employez la casse kebab comme indiqué ci-dessous :If you want use the [HtmlTargetElement] attribute, you would use kebab case as shown below:

    [HtmlTargetElement("Website-Information")]
    
    • Les éléments de fermeture automatique n’ont aucun contenu.Elements that are self-closing have no content. Pour cet exemple, le balisage Razor utilise une balise de fermeture automatique, mais le Tag Helper crée un élément section (qui ne se ferme pas automatiquement et vous écrivez le contenu à l’intérieur de l’élément section).For this example, the Razor markup will use a self-closing tag, but the tag helper will be creating a section element (which isn't self-closing and you are writing content inside the section element). Par conséquent, vous devez affecter à TagMode la valeur StartTagAndEndTag pour écrire la sortie.Therefore, you need to set TagMode to StartTagAndEndTag to write output. Sinon, vous pouvez commenter le paramètre de ligne TagMode et écrire le balisage avec une balise de fermeture.Alternatively, you can comment out the line setting TagMode and write markup with a closing tag. (Un exemple de balisage est fourni plus loin dans ce didacticiel.)(Example markup is provided later in this tutorial.)

    • Le signe $ (signe dollar) de la ligne suivante utilise une chaîne interpolée :The $ (dollar sign) in the following line uses an interpolated string:

    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    
  4. Ajoutez le balisage suivant à la vue About.cshtml.Add the following markup to the About.cshtml view. Le balisage en surbrillance affiche les informations de site web.The highlighted markup displays the web site information.

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

    Notes

    Dans le balisage Razor indiqué ci-dessous :In the Razor markup shown below:

    <website-information info="webContext" />
    

    Razor identifie que l’attribut info est une classe, et non une chaîne, et que vous souhaitez écrire du code C#.Razor knows the info attribute is a class, not a string, and you want to write C# code. N’importe quel attribut de Tag Helper autre qu’une chaîne doit être écrit sans le caractère @.Any non-string tag helper attribute should be written without the @ character.

  5. Exécutez l’application et accédez à la vue About (À propos de) pour afficher les informations de site web.Run the app, and navigate to the About view to see the web site information.

    Notes

    Vous pouvez utiliser le balisage suivant avec une balise de fermeture et supprimer la ligne avec TagMode.StartTagAndEndTag dans le Tag Helper :You can use the following markup with a closing tag and remove the line with TagMode.StartTagAndEndTag in the tag helper:

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

Tag Helper ConditionCondition Tag Helper

Le Tag Helper Condition restitue la sortie quand une valeur true lui est transmise.The condition tag helper renders output when passed a true value.

  1. Ajoutez la classe ConditionTagHelper suivante au dossier TagHelpers.Add the following ConditionTagHelper class to the TagHelpers folder.

    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. Remplacez le contenu du fichier Views/Home/Index.cshtml par le balisage suivant :Replace the contents of the Views/Home/Index.cshtml file with the following 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. Remplacez la méthode Index dans le contrôleur Home par le code suivant :Replace the Index method in the Home controller with the following 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. Exécutez l’application et accédez à la page d’accueil.Run the app and browse to the home page. Le balisage de l’élément div conditionnel ne sera pas rendu.The markup in the conditional div won't be rendered. Ajoutez la chaîne de requête ?approved=true à l’URL (par exemple, http://localhost:1235/Home/Index?approved=true).Append the query string ?approved=true to the URL (for example, http://localhost:1235/Home/Index?approved=true). approved a la valeur true et le balisage conditionnel s’affichera.approved is set to true and the conditional markup will be displayed.

Notes

Utilisez l’opérateur nameof pour spécifier l’attribut à cibler plutôt qu’une chaîne comme vous le faisiez avec le Tag Helper Bold :Use the nameof operator to specify the attribute to target rather than specifying a string as you did with the 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();
      }
   }
}

L’opérateur nameof protégera le code s’il devait jamais être refactorisé (le nom peut être changé en RedCondition).The nameof operator will protect the code should it ever be refactored (we might want to change the name to RedCondition).

Éviter les conflits de Tag HelpersAvoid Tag Helper conflicts

Dans cette section, vous écrivez une paire de Tag Helpers de liaison automatique.In this section, you write a pair of auto-linking tag helpers. Le premier remplace le balisage contenant une URL commençant par HTTP par une balise d’ancrage HTML contenant la même URL (et produisant ainsi un lien vers l’URL).The first will replace markup containing a URL starting with HTTP to an HTML anchor tag containing the same URL (and thus yielding a link to the URL). Le second effectue la même opération pour une URL commençant par WWW.The second will do the same for a URL starting with WWW.

Comme ces deux Tag Helpers sont étroitement liés et que vous pouvez les refactoriser à l’avenir, nous allons les conserver dans le même fichier.Because these two helpers are closely related and you may refactor them in the future, we'll keep them in the same file.

  1. Ajoutez la classe AutoLinkerHttpTagHelper suivante au dossier TagHelpers.Add the following AutoLinkerHttpTagHelper class to the TagHelpers folder.

    [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

    La classe AutoLinkerHttpTagHelper cible les éléments p et utilise Regex pour créer l’ancre.The AutoLinkerHttpTagHelper class targets p elements and uses Regex to create the anchor.

  2. Ajoutez le balisage suivant à la fin du fichier Views/Home/Contact.cshtml :Add the following markup to the end of the Views/Home/Contact.cshtml file:

    @{
        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. Exécutez l’application et vérifiez que le Tag Helper restitue correctement l’ancre.Run the app and verify that the tag helper renders the anchor correctly.

  4. Mettez à jour la classe AutoLinker pour inclure AutoLinkerWwwTagHelper qui convertira le texte www en une balise d’ancrage qui contient également le texte www d’origine.Update the AutoLinker class to include the AutoLinkerWwwTagHelper which will convert www text to an anchor tag that also contains the original www text. Le code mis à jour est en surbrillance ci-dessous :The updated code is highlighted below:

        [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. Exécutez l'application.Run the app. Notez que le texte www est affiché sous forme de lien, contrairement au texte HTTP.Notice the www text is rendered as a link but the HTTP text isn't. Si vous placez un point d’arrêt dans les deux classes, vous pouvez voir que la classe du Tag Helper HTTP s’exécute en premier.If you put a break point in both classes, you can see that the HTTP tag helper class runs first. Le problème est que la sortie du Tag Helper est mise en cache et, quand le Tag Helper WWW est exécuté, il remplace la sortie mise en cache du Tag Helper HTTP.The problem is that the tag helper output is cached, and when the WWW tag helper is run, it overwrites the cached output from the HTTP tag helper. Plus loin dans ce didacticiel, nous verrons comment contrôler l’ordre d’exécution des Tag Helpers.Later in the tutorial we'll see how to control the order that tag helpers run in. Nous allons corriger le code avec les éléments suivants :We'll fix the code with the following:

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

    Notes

    Dans la première édition des Tag Helpers de liaison automatique, vous avez obtenu le contenu de la cible avec le code suivant :In the first edition of the auto-linking tag helpers, you got the content of the target with the following code:

    var childContent = await output.GetChildContentAsync();
    

    Autrement dit, vous appelez GetChildContentAsync à l’aide de l’élément TagHelperOutput passé dans la méthode ProcessAsync.That is, you call GetChildContentAsync using the TagHelperOutput passed into the ProcessAsync method. Comme mentionné précédemment, étant donné que la sortie est mise en cache, le dernier Tag Helper qui est exécuté l’emporte.As mentioned previously, because the output is cached, the last tag helper to run wins. Vous avez résolu ce problème avec le code suivant :You fixed that problem with the following code:

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

    Le code ci-dessus vérifie si le contenu a été modifié et, le cas échéant, obtient le contenu à partir de la mémoire tampon de sortie.The code above checks to see if the content has been modified, and if it has, it gets the content from the output buffer.

  6. Exécutez l’application et vérifiez que les deux liens fonctionnent comme prévu.Run the app and verify that the two links work as expected. Alors qu’il peut sembler que notre Tag Helper de liaison automatique est correct et terminé, il pose un problème subtil.While it might appear our auto linker tag helper is correct and complete, it has a subtle problem. Si le Tag Helper WWW est exécuté en premier, les liens www ne sont pas corrects.If the WWW tag helper runs first, the www links won't be correct. Mettez à jour le code en ajoutant la surcharge Order pour contrôler l’ordre d’exécution des Tag Helpers.Update the code by adding the Order overload to control the order that the tag runs in. La propriété Order détermine l’ordre d’exécution par rapport à d’autres Tag Helpers ciblant le même élément.The Order property determines the execution order relative to other tag helpers targeting the same element. La valeur d’ordre par défaut est égale à zéro et les instances ayant des valeurs inférieures sont exécutées en premier.The default order value is zero and instances with lower values are executed first.

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

    Le code précédent garantit que le Tag Helper HTTP s’exécute avant le Tag Helper WWW.The preceding code guarantees that the HTTP tag helper runs before the WWW tag helper. Remplacez Order par MaxValue et vérifiez que le balisage généré pour la balise WWW est incorrect.Change Order to MaxValue and verify that the markup generated for the WWW tag is incorrect.

Examiner et récupérer le contenu enfantInspect and retrieve child content

Les Tag Helpers fournissent plusieurs propriétés permettant de récupérer le contenu.The tag helpers provide several properties to retrieve content.

  • Le résultat de GetChildContentAsync peut être ajouté à output.Content.The result of GetChildContentAsync can be appended to output.Content.
  • Vous pouvez examiner le résultat de GetChildContentAsync avec GetContent.You can inspect the result of GetChildContentAsync with GetContent.
  • Si vous modifiez output.Content, le corps TagHelper n’est pas exécuté ni restitué, sauf si vous appelez GetChildContentAsync comme dans notre exemple de liaison automatique :If you modify output.Content, the TagHelper body won't be executed or rendered unless you call GetChildContentAsync as in our auto-linker sample:
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}
    }
}
  • Plusieurs appels à GetChildContentAsync retournent la même valeur et ne réexécutent pas le corps TagHelper, sauf si vous passez un paramètre false indiquant de ne pas utiliser le résultat mis en cache.Multiple calls to GetChildContentAsync returns the same value and doesn't re-execute the TagHelper body unless you pass in a false parameter indicating not to use the cached result.

Charger TagHelper avec une vue partielle minimiséeLoad minified partial view TagHelper

Dans les environnements de production, les performances peuvent être améliorées en chargeant des vues partielles minimisées.In production environments, performance can be improved by loading minified partial views. Pour tirer parti de la vue partielle minimisée en production :To take advantage of minified partial view in production:

  • Créez/configurez un processus pré-build qui minimise les vues partielles.Create/set up a pre-build process that minifies partial views.
  • Utilisez le code suivant pour charger des vues partielles minimisées dans des environnements non liés au développement.Use the following code to load minified partial views in non-development environments.
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;
        }
    }