Komponenty pomocných rutin značek v ASP.NET Core

Scott Addie a Fiyaz Bin Hasan

Pomocná komponenta značky je pomocník značky, který umožňuje podmíněně upravovat nebo přidávat elementy HTML z kódu na straně serveru. Tato funkce je dostupná ve verzi ASP.NET Core 2.0 nebo novější.

ASP.NET Core obsahuje dvě integrované součásti pomocné rutiny značek: head a body. Nacházejí se v Microsoft.AspNetCore.Mvc.Razor.TagHelpers oboru názvů a dají se použít v MVC i Razor Pages. Pomocné komponenty značek nevyžadují registraci v aplikaci ._ViewImports.cshtml

Zobrazení nebo stažení ukázkového kódu (postup stažení)

Případy použití

Mezi dva běžné případy použití pomocných komponent značek patří:

  1. Injektáže <link> do <head>.
  2. Injektáže <script> do <body>.

Následující části popisují tyto případy použití.

Vložení do hlavního elementu HTML

Uvnitř elementu HTML <head> se soubory CSS běžně importují s elementem HTML <link> . Následující kód vloží <link> prvek do <head> elementu head pomocí komponenty Tag Helper:

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

V předchozím kódu:

  • AddressStyleTagHelperComponent implementuje TagHelperComponent. Abstrakce:
    • Umožňuje inicializaci třídy pomocí .TagHelperContext
    • Umožňuje použití pomocných komponent značek k přidání nebo úpravě elementů HTML.
  • Vlastnost Order definuje pořadí, ve kterém jsou součásti vykresleny. Order je nezbytné, pokud v aplikaci existuje více použití pomocných komponent značek.
  • ProcessAsync porovná hodnotu vlastnosti kontextu TagName provádění s headhodnotou . Pokud se porovnání vyhodnotí jako true, obsah _style pole se vloží do elementu HTML <head> .

Vložení do elementu textu HTML

Komponenta body Pomocné rutiny značky může vložit <script> prvek do elementu <body> . Následující kód ukazuje tuto techniku:

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

K uložení elementu <script> se používá samostatný soubor HTML. Soubor HTML zajistí, aby byl kód čistější a lépe udržovatelný. Předchozí kód přečte obsah TagHelpers/Templates/AddressToolTipScript.html a připojí ho pomocí výstupu pomocné rutiny značky. Soubor AddressToolTipScript.html obsahuje následující kód:

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

Předchozí kód vytvoří vazbu widgetu popisu bootstrap na jakýkoli <address> prvek, který obsahuje printable atribut. Efekt je viditelný, když ukazatel myši najede na prvek.

Registrace komponenty

Součást Pomocné rutiny značek musí být přidána do kolekce pomocných komponent značek aplikace. Do kolekce se dají přidat třemi způsoby:

Registrace prostřednictvím kontejneru služeb

Pokud není spravovaná třída ITagHelperComponentManagerkomponenty Pomocné rutiny značek , musí být registrována v systému injektáž závislostí (DI). Následující Startup.ConfigureServices kód zaregistruje AddressStyleTagHelperComponent a AddressScriptTagHelperComponent třídy s přechodnou životností:

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

Registrace prostřednictvím Razor souboru

Pokud není součást pomocné rutiny značky zaregistrovaná v DI, je možné ji zaregistrovat ze Razor stránky stránky nebo zobrazení MVC. Tato technika se používá k řízení vložených značek a pořadí provádění komponent ze Razor souboru.

ITagHelperComponentManager slouží k přidání pomocných komponent značek nebo k jejich odebrání z aplikace. Následující kód ukazuje tuto techniku s 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));
}

V předchozím kódu:

  • Směrnice @inject poskytuje instanci ITagHelperComponentManager. Instance je přiřazena k proměnné pojmenované manager pro přístup do podřízeného objektu Razor v souboru.
  • Do kolekce pomocných AddressTagHelperComponent komponent značek aplikace se přidá instance.

AddressTagHelperComponent je upraven tak, aby vyhovoval konstruktoru, který přijímá markup parametry order :

private readonly string _markup;

public override int Order { get; }

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

markup Zadaný parametr se používá ProcessAsync takto:

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

Registrace prostřednictvím modelu stránky nebo kontroleru

Pokud není pomocná komponenta značky zaregistrovaná v DI, je možné ji zaregistrovat z Razor modelu stránky stránky nebo kontroleru MVC. Tato technika je užitečná pro oddělení logiky jazyka C# od Razor souborů.

Injektáž konstruktoru se používá pro přístup k instanci ITagHelperComponentManager. Součást Pomocné rutiny značek se přidá do kolekce komponent pomocné rutiny značek instance. Razor Následující model stránky Stránky ukazuje tuto techniku sAddressTagHelperComponent:

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

V předchozím kódu:

  • Injektáž konstruktoru se používá pro přístup k instanci ITagHelperComponentManager.
  • Do kolekce pomocných AddressTagHelperComponent komponent značek aplikace se přidá instance.

Vytvoření komponenty

Vytvoření vlastní pomocné komponenty značek:

Následující kód vytvoří vlastní pomocnou komponentu značky, která cílí na <address> element HTML:

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

Pomocí vlastní address pomocné komponenty značek vkládat kód HTML následujícím způsobem:

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

Předchozí ProcessAsync metoda vloží kód HTML zadaný do SetHtmlContent odpovídajícího <address> elementu. Injektáž nastane v následujících případech:

  • Hodnota vlastnosti kontextu TagName spuštění se addressrovná .
  • <address> Odpovídající prvek má printable atribut.

Například příkaz if se vyhodnotí jako true při zpracování následujícího <address> prvku:

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

Další prostředky