Share via


Componenti helper tag in ASP.NET Core

Di Scott Addie e Fiyaz Bin Hasan

Un componente helper tag è un helper tag che consente di modificare o aggiungere elementi HTML da codice lato server in modo condizionale. Questa funzionalità è disponibile in ASP.NET Core 2.0 o versioni successive.

ASP.NET Core include due componenti helper tag predefiniti: head e body. Si trovano nello spazio dei Microsoft.AspNetCore.Mvc.Razor.TagHelpers nomi e possono essere usati sia in MVC Razor che in Pages. I componenti helper tag non richiedono la registrazione con l'app in _ViewImports.cshtml.

Visualizzare o scaricare il codice di esempio (procedura per il download)

Casi d'uso

Due casi d'uso comuni dei componenti helper tag sono:

  1. Inserimento di un <link> nell'elemento <head>.
  2. Inserimento di un <script> nell'elemento <body>.

Le sezioni seguenti descrivono questi casi d'uso.

Inserire in un elemento HTML head

All'interno dell'elemento HTML <head> i file CSS vengono generalmente importati con l'elemento HTML <link>. Il codice seguente inserisce un elemento <link> nell'elemento <head> usando il componente helper tag head:

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace RazorPagesSample.TagHelpers
{
    public class AddressStyleTagHelperComponent : TagHelperComponent
    {
        private readonly string _style = 
            @"<link rel=""stylesheet"" href=""/css/address.css"" />";

        public override int Order => 1;

        public override Task ProcessAsync(TagHelperContext context,
                                          TagHelperOutput output)
        {
            if (string.Equals(context.TagName, "head", 
                              StringComparison.OrdinalIgnoreCase))
            {
                output.PostContent.AppendHtml(_style);
            }

            return Task.CompletedTask;
        }
    }
}

Nel codice precedente:

  • AddressStyleTagHelperComponent implementa TagHelperComponent. Astrazione:
    • Consente l'inizializzazione della classe con un TagHelperContext.
    • Abilita l'uso dei componenti helper tag per l'aggiunta o la modifica di elementi HTML.
  • La proprietà Order definisce l'ordine in cui viene eseguito il rendering dei componenti. Order è necessaria in presenza di più utilizzi dei componenti helper tag in un'app.
  • ProcessAsync confronta il valore della proprietà TagName del contesto di esecuzione con head. Se il confronto restituisce true, il contenuto del campo _style viene inserito nell'elemento HTML <head>.

Inserire in un elemento HTML body

Il componente helper tag body può inserire un elemento <script> nell'elemento <body>. Questa tecnica è illustrata nel codice riportato di seguito:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace RazorPagesSample.TagHelpers
{
    public class AddressScriptTagHelperComponent : TagHelperComponent
    {
        public override int Order => 2;
        
        public override async Task ProcessAsync(TagHelperContext context,
                                                TagHelperOutput output)
        {
            if (string.Equals(context.TagName, "body",
                              StringComparison.OrdinalIgnoreCase))
            {
                var script = await File.ReadAllTextAsync(
                    "TagHelpers/Templates/AddressToolTipScript.html");
                output.PostContent.AppendHtml(script);
            }
        }
    }
}

Per archiviare l'elemento <script> viene usato un file HTML separato, che rende il codice più lineare e gestibile. Il codice precedente legge il contenuto di TagHelpers/Templates/AddressToolTipScript.html e lo aggiunge all'output dell'helper tag. Il AddressToolTipScript.html file include il markup seguente:

<script>
$("address[printable]").hover(function() {
    $(this).attr({
        "data-toggle": "tooltip",
        "data-placement": "right",
        "title": "Home of Microsoft!"
    });
});
</script>

Il codice precedente associa un widget tooltip Boostrap a qualsiasi elemento <address> che include un attributo printable. L'effetto è visibile quando si posiziona il puntatore del mouse sull'elemento.

Registrare un componente

Un componente helper tag deve essere aggiunto alla raccolta di componenti helper tag. È possibile farlo in tre modi:

Registrazione tramite un contenitore di servizi

Se la classe di componenti helper tag non è gestita con ITagHelperComponentManager, deve essere registrata con il sistema di inserimento delle dipendenze. Il codice Startup.ConfigureServices seguente registra le classi AddressStyleTagHelperComponent e AddressScriptTagHelperComponent con una durata temporanea:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddTransient<ITagHelperComponent, 
        AddressScriptTagHelperComponent>();
    services.AddTransient<ITagHelperComponent, 
        AddressStyleTagHelperComponent>();
}

Registrazione tramite Razor file

Se il componente helper tag non è registrato con l'inserimento delle dipendenze, può essere registrato da una pagina Pages o da una Razor visualizzazione MVC. Questa tecnica viene usata per controllare il markup inserito e l'ordine di esecuzione del componente da un Razor file.

ITagHelperComponentManager viene usato per aggiungere componenti helper tag o per rimuoverli dall'app. Il codice seguente illustra questa tecnica con AddressTagHelperComponent:

@using RazorPagesSample.TagHelpers;
@using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
@inject ITagHelperComponentManager manager;

@{
    string markup;

    if (Model.IsWeekend)
    {
        markup = "<em class='text-warning'>Office closed today!</em>";
    }
    else
    {
        markup = "<em class='text-info'>Office open today!</em>";
    }

    manager.Components.Add(new AddressTagHelperComponent(markup, 1));
}

Nel codice precedente:

  • La direttiva @inject fornisce un'istanza di ITagHelperComponentManager. L'istanza viene assegnata a una variabile denominata manager per l'accesso downstream nel Razor file.
  • Un'istanza di AddressTagHelperComponent viene aggiunta alla raccolta di componenti helper tag dell'app.

AddressTagHelperComponent viene modificato per contenere un costruttore che accetta i parametri markup e order:

private readonly string _markup;

public override int Order { get; }

public AddressTagHelperComponent(string markup = "", int order = 1)
{
    _markup = markup;
    Order = order;
}

Il parametro markup specificato viene usato in ProcessAsync nel modo seguente:

public override async Task ProcessAsync(TagHelperContext context,
                                        TagHelperOutput output)
{
    if (string.Equals(context.TagName, "address",
            StringComparison.OrdinalIgnoreCase) &&
        output.Attributes.ContainsName("printable"))
    {
        TagHelperContent childContent = await output.GetChildContentAsync();
        string content = childContent.GetContent();
        output.Content.SetHtmlContent(
            $"<div>{content}<br>{_markup}</div>{_printableButton}");
    }
}

Registrazione tramite un modello di pagina o un controller

Se il componente helper tag non è registrato con l'inserimento delle dipendenze, può essere registrato da un Razor modello di pagina Pages o da un controller MVC. Questa tecnica è utile per separare la logica C# dai Razor file.

Per accedere a un'istanza di ITagHelperComponentManager viene usato l'inserimento del costruttore. Il componente helper tag deve viene aggiunto alla raccolta di componenti helper tag dell'istanza. Il modello di pagina Pages seguente Razor illustra questa tecnica con AddressTagHelperComponent:

using System;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesSample.TagHelpers;

public class IndexModel : PageModel
{
    private readonly ITagHelperComponentManager _tagHelperComponentManager;

    public bool IsWeekend
    {
        get
        {
            var dayOfWeek = DateTime.Now.DayOfWeek;

            return dayOfWeek == DayOfWeek.Saturday ||
                   dayOfWeek == DayOfWeek.Sunday;
        }
    }

    public IndexModel(ITagHelperComponentManager tagHelperComponentManager)
    {
        _tagHelperComponentManager = tagHelperComponentManager;
    }

    public void OnGet()
    {
        string markup;

        if (IsWeekend)
        {
            markup = "<em class='text-warning'>Office closed today!</em>";
        }
        else
        {
            markup = "<em class='text-info'>Office open today!</em>";
        }

        _tagHelperComponentManager.Components.Add(
            new AddressTagHelperComponent(markup, 1));
    }
}

Nel codice precedente:

  • Per accedere a un'istanza di ITagHelperComponentManager viene usato l'inserimento del costruttore.
  • Un'istanza di AddressTagHelperComponent viene aggiunta alla raccolta di componenti helper tag dell'app.

Creare un componente

Per creare un componente helper tag personalizzato:

Il codice seguente crea un componente helper tag personalizzato che fa riferimento all'elemento HTML <address>:

using System.ComponentModel;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Logging;

namespace RazorPagesSample.TagHelpers
{
    [HtmlTargetElement("address")]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public class AddressTagHelperComponentTagHelper : TagHelperComponentTagHelper
    {
        public AddressTagHelperComponentTagHelper(
            ITagHelperComponentManager componentManager, 
            ILoggerFactory loggerFactory) : base(componentManager, loggerFactory)
        {
        }
    }
}

Usare il componente helper tag personalizzato address per inserire markup HTML nel modo seguente:

public class AddressTagHelperComponent : TagHelperComponent
{
    private readonly string _printableButton =
        "<button type='button' class='btn btn-info' onclick=\"window.open(" +
        "'https://binged.it/2AXRRYw')\">" +
        "<span class='glyphicon glyphicon-road' aria-hidden='true'></span>" +
        "</button>";

    public override int Order => 3;

    public override async Task ProcessAsync(TagHelperContext context,
                                            TagHelperOutput output)
    {
        if (string.Equals(context.TagName, "address",
                StringComparison.OrdinalIgnoreCase) &&
            output.Attributes.ContainsName("printable"))
        {
            var content = await output.GetChildContentAsync();
            output.Content.SetHtmlContent(
                $"<div>{content.GetContent()}</div>{_printableButton}");
        }
    }
}

Il metodo ProcessAsync precedente inserisce l'HTML fornito a SetHtmlContent nell'elemento <address> corrispondente. L'inserimento si verifica quando:

  • Il valore della proprietà TagName del contesto di esecuzione è uguale a address.
  • L'elemento <address> corrispondente ha un attributo printable.

Ad esempio, l'istruzione if restituisce true durante l'elaborazione dell'elemento <address> seguente:

<address printable>
    One Microsoft Way<br />
    Redmond, WA 98052-6399<br />
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

Risorse aggiuntive