Składniki pomocników tagów na platformie ASP.NET Core

Autor : Scott Addie i Fiyaz Bin Hasan

Składnik pomocnika tagów to pomocnik tagów, który umożliwia warunkowe modyfikowanie lub dodawanie elementów HTML z kodu po stronie serwera. Ta funkcja jest dostępna w wersji ASP.NET Core 2.0 lub nowszej.

ASP.NET Core zawiera dwa wbudowane składniki pomocnika tagów: head i body. Znajdują się one w Microsoft.AspNetCore.Mvc.Razor.TagHelpers przestrzeni nazw i mogą być używane zarówno w mvC, jak i Razor na stronach. Składniki pomocnika tagów nie wymagają rejestracji w aplikacji w programie _ViewImports.cshtml.

Wyświetl lub pobierz przykładowy kod (jak pobrać)

Przypadki użycia

Istnieją dwa typowe przypadki użycia składników pomocnika tagów:

  1. Wstrzykiwanie do <link> pliku <head>.
  2. Wstrzykiwanie do <script> pliku <body>.

W poniższych sekcjach opisano te przypadki użycia.

Wstrzykiwanie do elementu głównego HTML

Wewnątrz elementu HTML <head> pliki CSS są często importowane z elementem HTML <link> . Poniższy kod wprowadza <link> element do <head> elementu przy użyciu składnika Pomocnika tagów 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;
        }
    }
}

Powyższy kod:

  • AddressStyleTagHelperComponent implementuje TagHelperComponent. Abstrakcja:
    • Umożliwia inicjowanie klasy za pomocą klasy TagHelperContext.
    • Umożliwia używanie składników pomocnika tagów do dodawania lub modyfikowania elementów HTML.
  • Właściwość Order definiuje kolejność renderowania składników. Order jest konieczne, gdy w aplikacji istnieje wiele użycia składników pomocnika tagów.
  • ProcessAsync porównuje wartość właściwości kontekstu TagName wykonywania z headwartością . Jeśli porównanie daje wartość true, zawartość _style pola jest wstrzykiwana do elementu HTML <head> .

Wstrzykiwanie do elementu treści HTML

body Składnik pomocnika tagów może wstrzyknąć <script> element do <body> elementu. Poniższy kod demonstruje tę technikę:

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

Do przechowywania elementu służy oddzielny <script> plik HTML. Plik HTML sprawia, że kod jest czystszy i bardziej konserwowalny. Powyższy kod odczytuje zawartość TagHelpers/Templates/AddressToolTipScript.html elementu i dołącza ją do danych wyjściowych pomocnika tagów. Plik AddressToolTipScript.html zawiera następujące znaczniki:

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

Powyższy kod wiąże widżet etykietki narzędzia Bootstrap z dowolnym <address> elementem zawierającym printable atrybut. Efekt jest widoczny, gdy wskaźnik myszy najecha kursorem na element.

Rejestrowanie składnika

Składnik pomocnika tagów musi zostać dodany do kolekcji składników pomocnika tagów aplikacji. Istnieją trzy sposoby dodawania do kolekcji:

Rejestracja za pośrednictwem kontenera usług

Jeśli klasa składników pomocnika tagów nie jest zarządzana za pomocą ITagHelperComponentManagerpolecenia , musi zostać zarejestrowana w systemie wstrzykiwania zależności (DI). Poniższy kod rejestruje AddressStyleTagHelperComponent klasy i AddressScriptTagHelperComponent z okresem przejściowym:Startup.ConfigureServices

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

Rejestracja za pośrednictwem Razor pliku

Jeśli składnik pomocnika tagów nie jest zarejestrowany w usłudze DI, można go zarejestrować ze Razor strony stron lub widoku MVC. Ta technika służy do kontrolowania wprowadzonego znacznika i kolejności wykonywania składnika z Razor pliku.

ITagHelperComponentManager służy do dodawania składników pomocnika tagów lub usuwania ich z aplikacji. Poniższy kod demonstruje tę technikę za pomocą AddressTagHelperComponentpolecenia :

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

Powyższy kod:

  • Dyrektywa @inject udostępnia wystąpienie ITagHelperComponentManagerklasy . Wystąpienie jest przypisywane do zmiennej o nazwie manager dla dostępu podrzędnego Razor w pliku .
  • Wystąpienie AddressTagHelperComponent elementu jest dodawane do kolekcji Składników pomocnika tagów aplikacji.

AddressTagHelperComponent element jest modyfikowany w celu uwzględnienia konstruktora, który akceptuje markup parametry i order :

private readonly string _markup;

public override int Order { get; }

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

Podany markup parametr jest używany w następujący ProcessAsync sposób:

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

Rejestracja za pomocą modelu strony lub kontrolera

Jeśli składnik pomocnika tagów nie jest zarejestrowany w usłudze DI, można go zarejestrować z Razor modelu strony stron lub kontrolera MVC. Ta technika jest przydatna do oddzielania logiki języka C# od Razor plików.

Wstrzykiwanie konstruktora służy do uzyskiwania ITagHelperComponentManagerdostępu do wystąpienia klasy . Składnik pomocnika tagów jest dodawany do kolekcji składników pomocnika tagów wystąpienia. Razor Poniższy model strony Strony demonstruje tę technikę za pomocą AddressTagHelperComponentpolecenia :

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

Powyższy kod:

  • Wstrzykiwanie konstruktora służy do uzyskiwania ITagHelperComponentManagerdostępu do wystąpienia klasy .
  • Wystąpienie AddressTagHelperComponent elementu jest dodawane do kolekcji Składników pomocnika tagów aplikacji.

Tworzenie składnika

Aby utworzyć niestandardowy składnik pomocnika tagów:

Poniższy kod tworzy niestandardowy składnik pomocnika tagów, który jest przeznaczony dla <address> elementu 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)
        {
        }
    }
}

Użyj niestandardowego address składnika pomocnika tagów, aby wstrzyknąć znaczniki HTML w następujący sposób:

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

Poprzednia ProcessAsync metoda wprowadza kod HTML podany do SetHtmlContent pasującego <address> elementu. Iniekcja występuje, gdy:

  • Wartość właściwości kontekstu TagName wykonywania jest addressrówna .
  • Odpowiedni <address> element ma printable atrybut.

Na przykład if instrukcja zwraca wartość true podczas przetwarzania następującego <address> elementu:

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

Dodatkowe zasoby