Creare helper tag in ASP.NET CoreAuthor Tag Helpers in ASP.NET Core

Di Rick AndersonBy Rick Anderson

Visualizzare o scaricare il codice di esempio (procedura per il download)View or download sample code (how to download)

Guida introduttiva agli helper tagGet started with Tag Helpers

Questa esercitazione rappresenta un'introduzione alla programmazione di helper tag.This tutorial provides an introduction to programming Tag Helpers. Introduzione agli helper tag descrive i vantaggi offerti dagli helper tag.Introduction to Tag Helpers describes the benefits that Tag Helpers provide.

Un helper tag è una classe che implementa l'interfaccia ITagHelper.A tag helper is any class that implements the ITagHelper interface. Quando si crea un helper tag, tuttavia, in genere lo si deriva da TagHelper. In questo modo si ottiene l'accesso al metodo Process.However, when you author a tag helper, you generally derive from TagHelper, doing so gives you access to the Process method.

  1. Creare un nuovo progetto ASP.NET Core denominato AuthoringTagHelpers.Create a new ASP.NET Core project called AuthoringTagHelpers. Per questo progetto non sarà necessaria l'autenticazione.You won't need authentication for this project.

  2. Creare una cartella che contenga gli helper tag denominata TagHelpers.Create a folder to hold the Tag Helpers called TagHelpers. La cartella TagHelpers non è obbligatoria, ma rappresenta una convenzione sensata.The TagHelpers folder is not required, but it's a reasonable convention. È ora possibile iniziare a scrivere alcuni helper tag semplici.Now let's get started writing some simple tag helpers.

Un helper tag piccolissimoA minimal Tag Helper

In questa sezione verrà scritto un helper tag che aggiorna un tag di posta elettronica.In this section, you write a tag helper that updates an email tag. Ad esempio:For example:

<email>Support</email>

Il server userà l'helper tag di posta elettronica creato per convertire il markup nel codice seguente: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>

In altre parole, un tag di ancoraggio che dà come risultato un collegamento di posta elettronica.That is, an anchor tag that makes this an email link. È necessario eseguire questa operazione se si sta scrivendo un motore di blog e si vuole inviare posta elettronica di marketing o di supporto ad altri contatti, tutti nello stesso dominio.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. Aggiungere la classe EmailTagHelper seguente alla cartella 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
            }
        }
    }
    
    • Gli helper tag usano una convenzione di denominazione che interessa gli elementi del nome della classe di base (meno la parte TagHelper del nome della classe).Tag helpers use a naming convention that targets elements of the root class name (minus the TagHelper portion of the class name). In questo esempio il nome radice di EmailTagHelper è email, pertanto il tag <email> viene considerato come destinazione.In this example, the root name of EmailTagHelper is email, so the <email> tag will be targeted. Questa convenzione di denominazione dovrebbe funzionare per la maggior parte degli helper tag. Più avanti verrà illustrato come eseguirne l'override.This naming convention should work for most tag helpers, later on I'll show how to override it.

    • La classe EmailTagHelper deriva da TagHelper.The EmailTagHelper class derives from TagHelper. La classe TagHelper mette a disposizione metodi e proprietà per la scrittura di helper tag.The TagHelper class provides methods and properties for writing Tag Helpers.

    • Il metodo Process sottoposto a override controlla ciò che l'helper tag fa quando viene eseguito.The overridden Process method controls what the tag helper does when executed. La classe TagHelper fornisce anche una versione asincrona (ProcessAsync) con gli stessi parametri.The TagHelper class also provides an asynchronous version (ProcessAsync) with the same parameters.

    • Il parametro context di Process (e ProcessAsync) contiene informazioni associate all'esecuzione del tag HTML corrente.The context parameter to Process (and ProcessAsync) contains information associated with the execution of the current HTML tag.

    • Il parametro output di Process (e ProcessAsync) contiene un elemento HTML con stato rappresentativo dell'origine originale usato per generare un tag e del contenuto HTML.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.

    • Il nome della classe usata ha il suffisso TagHelper, che non è obbligatorio, ma il cui uso è considerato una convenzione basata su procedure consigliate.Our class name has a suffix of TagHelper, which is not required, but it's considered a best practice convention. È possibile dichiarare la classe come:You could declare the class as:

    public class Email : TagHelper
    
  2. Per rendere la classe EmailTagHelper disponibile per tutte le visualizzazioni Razor in uso, aggiungere la direttiva addTagHelper al file 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
    

    Il codice qui sopra usa la sintassi con caratteri jolly per specificare che tutti gli helper tag in questo assembly saranno disponibili.The code above uses the wildcard syntax to specify all the tag helpers in our assembly will be available. La prima stringa dopo @addTagHelper specifica l'helper tag da caricare (usare "*" per indicare tutti gli helper tag), e la seconda stringa "AuthoringTagHelpers" specifica l'assembly in cui si trova l'helper tag.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. Si noti anche che la seconda riga introduce gli helper tag ASP.NET Core MVC tramite la sintassi con caratteri jolly. Questi helper sono trattati in Introduzione agli helper tag. È la direttiva @addTagHelper che rende l'helper tag disponibile per la visualizzazione 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. In alternativa, è possibile specificare il nome completo dell'helper tag, come illustrato di seguito: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

Per aggiungere un helper tag a una visualizzazione usando un nome completo, aggiungere prima il nome completo (AuthoringTagHelpers.TagHelpers.EmailTagHelper) e quindi il nome dell'assembly (AuthoringTagHelpers, non necessariamente 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 maggior parte degli sviluppatori preferisce usare la sintassi con caratteri jolly.Most developers will prefer to use the wildcard syntax. Introduzione agli helper tag descrive in dettaglio la sintassi di aggiunta, rimozione, gerarchia degli helper tag, nonché la sintassi con caratteri jolly.Introduction to Tag Helpers goes into detail on tag helper adding, removing, hierarchy, and wildcard syntax.

  1. Aggiornare il markup nel file Views/Home/Contact.cshtml con queste modifiche: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. Eseguire l'app e usare il browser preferito per visualizzare l'origine HTML e verificare che i tag di posta elettronica siano stati sostituiti dal markup di ancoraggio, ad esempio, <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 e Marketing sono visualizzati come collegamenti, ma non hanno un attributo href che li renda funzionali.Support and Marketing are rendered as a links, but they don't have an href attribute to make them functional. Questo problema verrà corretto nella prossima sezione.We'll fix that in the next section.

SetAttribute e SetContentSetAttribute and SetContent

In questa sezione la classe EmailTagHelper verrà aggiornata in modo che crei un tag di ancoraggio valido per la posta elettronica.In this section, we'll update the EmailTagHelper so that it will create a valid anchor tag for email. La classe verrà aggiornata in modo da ricevere informazioni da una visualizzazione Razor (sotto forma di un attributo mail-to) e in modo da usare tali informazioni per generare l'ancoraggio.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.

Aggiornare la classe EmailTagHelper con il codice seguente: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);
    }
}
  • I nomi della classe e delle proprietà per gli helper tag, scritti secondo la convenzione Pascal, vengono convertiti nel formato kebab case corrispondente.Pascal-cased class and property names for tag helpers are translated into their kebab case. Per usare l'attributo MailTo, pertanto, si userà l'equivalente <email mail-to="value"/>.Therefore, to use the MailTo attribute, you'll use <email mail-to="value"/> equivalent.

  • L'ultima riga imposta il contenuto completato per l'helper tag dalle minime funzioni.The last line sets the completed content for our minimally functional tag helper.

  • La riga evidenziata illustra la sintassi per l'aggiunta di attributi: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);
}

Questo approccio funziona per l'attributo "href" a condizione che non esista nella raccolta di attributi.That approach works for the attribute "href" as long as it doesn't currently exist in the attributes collection. È anche possibile usare il metodo output.Attributes.Add per aggiungere un attributo di helper tag alla fine della raccolta di attributi di tag.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. Aggiornare il markup nel file Views/Home/Contact.cshtml con queste modifiche: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. Eseguire l'app e verificare che generi collegamenti corretti.Run the app and verify that it generates the correct links.

Nota

Se si scrive il tag di posta elettronica a chiusura automatica (<email mail-to="Rick" />), anche l'output finale è a chiusura automatica.If you were to write the email tag self-closing (<email mail-to="Rick" />), the final output would also be self-closing. Per abilitare la possibilità di scrivere il tag solo con il tag di inizio (<email mail-to="Rick">) è necessario decorare la classe con il codice seguente:To enable the ability to write the tag with only a start tag (<email mail-to="Rick">) you must decorate the class with the following:

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

Con un helper tag di posta elettronica a chiusura automatica, l'output è <a href="mailto:Rick@contoso.com" />.With a self-closing email tag helper, the output would be <a href="mailto:Rick@contoso.com" />. I tag di ancoraggio a chiusura automatica non costituiscono codice HTML valido ed è quindi necessario evitare di crearli, ma può essere necessario creare un helper tag a chiusura automatica.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. Gli helper tag impostano il tipo della proprietà TagMode dopo la lettura di un tag.Tag helpers set the type of the TagMode property after reading a tag.

ProcessAsyncProcessAsync

In questa sezione verrà scritto un helper di posta elettronica asincrono.In this section, we'll write an asynchronous email helper.

  1. Sostituire la classe EmailTagHelper con il codice seguente: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);
        }
    }
    

    Note:Notes:

    • Questa versione usa il metodo ProcessAsync asincrono.This version uses the asynchronous ProcessAsync method. GetChildContentAsync asincrono restituisce un Task contenente TagHelperContent.The asynchronous GetChildContentAsync returns a Task containing the TagHelperContent.

    • Usare il parametro output per ottenere il contenuto dell'elemento HTML.Use the output parameter to get contents of the HTML element.

  2. Apportare le seguenti modifiche al file Views/Home/Contact.cshtml, in modo che l'helper tag possa ottenere la posta elettronica di destinazione.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. Eseguire l'app e verificare che generi collegamenti di posta elettronica validi.Run the app and verify that it generates valid email links.

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

  1. Aggiungere la classe BoldTagHelper seguente alla cartella 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'attributo [HtmlTargetElement] passa un parametro di attributo che specifica che qualsiasi elemento HTML che contenga un attributo HTML denominato "bold" corrisponderà e che quindi verrà eseguito il metodo di override Process nella classe.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. Nell'esempio, il metodo Process rimuove l'attributo "bold" e racchiude il markup tra <strong></strong>.In our sample, the Process method removes the "bold" attribute and surrounds the containing markup with <strong></strong>.

    • Dato che non si deve sostituire il contenuto esistente del tag, è necessario scrivere il tag <strong> di apertura con il metodo PreContent.SetHtmlContent e il tag </strong> di chiusura con il metodo 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. Modificare la visualizzazione About.cshtml in modo che contenga un valore di attributo bold.Modify the About.cshtml view to contain a bold attribute value. Il codice completo è illustrato di seguito.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. Eseguire l'app.Run the app. È possibile usare il browser preferito per controllare l'origine e verificare il markup.You can use your favorite browser to inspect the source and verify the markup.

    L'attributo [HtmlTargetElement] qui sopra ha come destinazione solo il markup HTML che fornisce un nome di attributo corrispondente a "bold".The [HtmlTargetElement] attribute above only targets HTML markup that provides an attribute name of "bold". L'elemento <bold> non è stato modificato dall'helper tag.The <bold> element wasn't modified by the tag helper.

  4. Impostare come commento la riga dell'attributo [HtmlTargetElement]. Per impostazione predefinita, userà quindi tag <bold>, vale a dire il markup HTML nel formato <bold>.Comment out the [HtmlTargetElement] attribute line and it will default to targeting <bold> tags, that is, HTML markup of the form <bold>. Tenere presente che la convenzione di denominazione predefinita corrisponderà al nome della classe BoldTagHelper per i tag <bold>.Remember, the default naming convention will match the class name BoldTagHelper to <bold> tags.

  5. Eseguire l'applicazione e verificare che il tag <bold> venga elaborato dall'helper tag.Run the app and verify that the <bold> tag is processed by the tag helper.

La decorazione di una classe con più attributi [HtmlTargetElement] risulta in un OR logico delle destinazioni.Decorating a class with multiple [HtmlTargetElement] attributes results in a logical-OR of the targets. Usando il codice riportato di seguito, ad esempio, un tag bold o un attributo bold corrisponderanno.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>");
    }
}

Se si aggiungono più attributi alla stessa istruzione, il runtime li gestisce come AND logici.When multiple attributes are added to the same statement, the runtime treats them as a logical-AND. Nel codice riportato di seguito, ad esempio, perché corrisponda, un elemento HTML deve essere denominato "bold" con un attributo denominato "bold" (<bold bold />).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")]

È anche possibile usare [HtmlTargetElement] per modificare il nome dell'elemento di destinazione.You can also use the [HtmlTargetElement] to change the name of the targeted element. Se ad esempio si vuole che BoldTagHelper abbia come destinazione tag <MyBold>, usare l'attributo seguente:For example if you wanted the BoldTagHelper to target <MyBold> tags, you would use the following attribute:

[HtmlTargetElement("MyBold")]

Passare un modello a un helper tagPass a model to a Tag Helper

  1. Aggiungere una cartella Models.Add a Models folder.

  2. Aggiungere la classe WebsiteContext seguente alla cartella 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. Aggiungere la classe WebsiteInformationTagHelper seguente alla cartella 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;
          }
       }
    }
    
    • Come affermato in precedenza, gli helper tag convertono i nomi delle relative classi e proprietà C#, definiti secondo la convenzione Pascal, in formato kebab case.As mentioned previously, tag helpers translates Pascal-cased C# class names and properties for tag helpers into kebab case. Per usare WebsiteInformationTagHelper in Razor, quindi, è necessario scrivere <website-information />.Therefore, to use the WebsiteInformationTagHelper in Razor, you'll write <website-information />.

    • Non si sta identificando in modo esplicito l'elemento di destinazione con l'attributo [HtmlTargetElement] e quindi verrà considerato come destinazione il valore predefinito di website-information.You are not explicitly identifying the target element with the [HtmlTargetElement] attribute, so the default of website-information will be targeted. Se è stato applicato l'attributo seguente (si noti che non è nel formato kebab case ma corrisponde al nome della classe):If you applied the following attribute (note it's not kebab case but matches the class name):

    [HtmlTargetElement("WebsiteInformation")]
    

    Il tag nel formato kebab case <website-information /> non corrisponde.The kebab case tag <website-information /> wouldn't match. Se si vuole usare l'attributo [HtmlTargetElement], è necessario usare il formato kebab case come illustrato di seguito:If you want use the [HtmlTargetElement] attribute, you would use kebab case as shown below:

    [HtmlTargetElement("Website-Information")]
    
    • Gli elementi a chiusura automatica non hanno contenuto.Elements that are self-closing have no content. Per questo esempio, il markup Razor userà un tag a chiusura automatica, ma l'helper tag creerà un elemento section, che non è a chiusura automatica, e si sta scrivendo contenuto all'interno dell'elemento 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). Per scrivere output, è pertanto necessario impostare TagMode su StartTagAndEndTag.Therefore, you need to set TagMode to StartTagAndEndTag to write output. In alternativa, è possibile impostare come commento la riga che imposta TagMode e scrivere markup con un tag di chiusura.Alternatively, you can comment out the line setting TagMode and write markup with a closing tag. Del markup di esempio viene fornito più avanti in questa esercitazione.(Example markup is provided later in this tutorial.)

    • Il simbolo $ (segno di dollaro) nella riga seguente usa una stringa interpolata:The $ (dollar sign) in the following line uses an interpolated string:

    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    
  4. Aggiungere il markup seguente alla visualizzazione About.cshtml.Add the following markup to the About.cshtml view. Il markup evidenziato visualizza le informazioni sul sito 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" />
    

    Nota

    Nel markup Razor illustrato di seguito:In the Razor markup shown below:

    <website-information info="webContext" />
    

    Razor sa che l'attributo info è una classe, non una stringa, e si vuole scrivere codice C#.Razor knows the info attribute is a class, not a string, and you want to write C# code. Qualsiasi attributo di helper tag non di tipo stringa deve essere scritto senza il carattere @.Any non-string tag helper attribute should be written without the @ character.

  5. Eseguire l'app e passare alla visualizzazione About per visualizzare le informazioni sul sito Web.Run the app, and navigate to the About view to see the web site information.

    Nota

    È possibile usare il markup seguente con un tag di chiusura e rimuovere la riga con TagMode.StartTagAndEndTag nell'helper tag: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>
    

Helper tag di condizioneCondition Tag Helper

L'helper tag di condizione esegue il rendering dell'output quando riceve un valore true.The condition tag helper renders output when passed a true value.

  1. Aggiungere la classe ConditionTagHelper seguente alla cartella 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. Sostituire il contenuto del file Views/Home/Index.cshtml con il markup seguente: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. Sostituire il metodo Index nel controller Home con il codice seguente: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. Eseguire l'app e passare alla home page.Run the app and browse to the home page. Non verrà eseguito il rendering del markup in div condizionale.The markup in the conditional div won't be rendered. Accodare la stringa di query ?approved=true all'URL (ad esempio, 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è impostato su true e il markup condizionale verrà visualizzato.approved is set to true and the conditional markup will be displayed.

Nota

Usare l'operatore nameof per specificare l'attributo di destinazione, anziché specificare una stringa, come è stato fatto per l'helper tag 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'operatore nameof proteggerà il codice nel caso venisse effettuato il refactoring (potrebbe essere necessario modificare il nome in RedCondition).The nameof operator will protect the code should it ever be refactored (we might want to change the name to RedCondition).

Evitare conflitti di helper tagAvoid Tag Helper conflicts

In questa sezione verrà scritta una coppia di helper tag a collegamento automatico.In this section, you write a pair of auto-linking tag helpers. Il primo sostituirà il markup contenente un URL che inizia con HTTP con un tag di ancoraggio HTML contenente lo stesso URL (e che quindi genera un collegamento all'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). Il secondo eseguirà la stessa operazione per un URL che inizia con WWW.The second will do the same for a URL starting with WWW.

Poiché questi due helper sono strettamente correlati e in futuro potrebbero essere sottoposti a refactoring, verranno mantenuti nello stesso file.Because these two helpers are closely related and you may refactor them in the future, we'll keep them in the same file.

  1. Aggiungere la classe AutoLinkerHttpTagHelper seguente alla cartella 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}
        }
    }
    

    Nota

    La classe AutoLinkerHttpTagHelper ha come destinazioni elementi p e usa Regex per creare l'ancoraggio.The AutoLinkerHttpTagHelper class targets p elements and uses Regex to create the anchor.

  2. Aggiungere il markup seguente alla fine del file 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. Eseguire l'app e verificare che l'helper tag esegua correttamente il rendering dell'ancoraggio.Run the app and verify that the tag helper renders the anchor correctly.

  4. Aggiornare la classe AutoLinker per includere AutoLinkerWwwTagHelper che convertirà il testo www in un tag di ancoraggio contenente anch'esso il testo www originale.Update the AutoLinker class to include the AutoLinkerWwwTagHelper which will convert www text to an anchor tag that also contains the original www text. Il codice aggiornato è evidenziato di seguito: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. Eseguire l'app.Run the app. Si noti che il testo www è visualizzato come collegamento, ma il testo HTTP non lo è.Notice the www text is rendered as a link but the HTTP text isn't. Se si inserisce un punto di interruzione in entrambe le classi, è possibile notare che la classe helper tag HTTP viene eseguita per prima.If you put a break point in both classes, you can see that the HTTP tag helper class runs first. Il problema è che l'output dell'helper tag viene memorizzato nella cache. Quando viene eseguito l'helper tag WWW, quest'ultimo sovrascrive l'output dell'helper tag HTTP memorizzato nella cache.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. Più avanti in questa esercitazione verrà illustrato come controllare l'ordine di esecuzione degli helper tag.Later in the tutorial we'll see how to control the order that tag helpers run in. È possibile correggere il problema con il codice seguente: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
          }
      }
    

    Nota

    Nella prima edizione degli helper tag a collegamento automatico, per ottenere il contenuto della destinazione è stato usato il codice seguente: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();
    

    In altre parole, si effettua una chiamata a GetChildContentAsync usando TagHelperOutput passato al metodo ProcessAsync.That is, you call GetChildContentAsync using the TagHelperOutput passed into the ProcessAsync method. Come affermato in precedenza, poiché l'output viene memorizzato nella cache, l'ultimo helper eseguito prevale.As mentioned previously, because the output is cached, the last tag helper to run wins. Il problema è stato risolto con il codice seguente:You fixed that problem with the following code:

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

    Il codice precedente controlla se il contenuto è stato modificato e, in caso affermativo, ottiene il contenuto dal buffer di output.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. Eseguire l'app e verificare che i due collegamenti funzionino come previsto.Run the app and verify that the two links work as expected. Può sembrare che l'helper tag a collegamento automatico sia corretto e completo, ma presenta un problema insidioso.While it might appear our auto linker tag helper is correct and complete, it has a subtle problem. Se l'helper tag WWW viene eseguito per primo, i collegamenti www non sono corretti.If the WWW tag helper runs first, the www links won't be correct. Aggiornare il codice aggiungendo l'overload Order per controllare l'ordine in cui viene eseguito il tag.Update the code by adding the Order overload to control the order that the tag runs in. La proprietà Order determina l'ordine di esecuzione rispetto agli altri helper tag che hanno come destinazione lo stesso elemento.The Order property determines the execution order relative to other tag helpers targeting the same element. Il valore dell'ordine predefinito è zero e le istanze con valori inferiori vengono eseguite per prime.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;   }
        }
    

    Il codice precedente assicura che l'helper tag HTTP venga eseguito prima dell'helper tag WWW.The preceding code guarantees that the HTTP tag helper runs before the WWW tag helper. Modificare Order in MaxValue e verificare che il markup generato per il tag WWW non è corretto.Change Order to MaxValue and verify that the markup generated for the WWW tag is incorrect.

Controllare e recuperare il contenuto figlioInspect and retrieve child content

Gli helper tag mettono a disposizione diverse proprietà per recuperare il contenuto.The tag helpers provide several properties to retrieve content.

  • Il risultato di GetChildContentAsync può essere accodato a output.Content.The result of GetChildContentAsync can be appended to output.Content.
  • È possibile controllare il risultato di GetChildContentAsync con GetContent.You can inspect the result of GetChildContentAsync with GetContent.
  • Se si modifica output.Content, il corpo di TagHelper viene eseguito, o ne viene eseguito il rendering, solo se si chiama GetChildContentAsync, come nell'esempio di helper tag a collegamento automatico: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}
    }
}
  • Più chiamate al metodo GetChildContentAsync restituiscono lo stesso valore e rieseguono nuovamente il corpo di TagHelper solo se viene passato un parametro false per indicare di non usare il risultato memorizzato nella 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.

TagHelper per caricare visualizzazioni parziali minimizzateLoad minified partial view TagHelper

Negli ambienti di produzione le prestazioni possono essere migliorate caricando visualizzazioni parziali minimizzate.In production environments, performance can be improved by loading minified partial views. Per sfruttare i vantaggi della visualizzazione parziale minimizzata nell'ambiente di produzione:To take advantage of minified partial view in production:

  • Creare/configurare un processo di pre-compilazione che minimizza visualizzazioni parziali.Create/set up a pre-build process that minifies partial views.
  • Usare il codice seguente per caricare le visualizzazioni parziali minimizzate in ambienti non di sviluppo.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;
        }
    }