共用方式為


ASP.NET Core 中的標籤協助程式元件

作者:Scott AddieFiyaz Bin Hasan

標籤協助程式元件是一種標籤協助程式,允許您從伺服器端程式碼有條件地修改或新增 HTML 項目。 ASP.NET Core 2.0 或更新版本提供此功能。

ASP.NET Core 包含兩個內建標籤協助程式元件:headbody。 它們會位於 Microsoft.AspNetCore.Mvc.Razor.TagHelpers 命名空間中,可用於 MVC 和 Razor Pages。 標籤協助程式元件不需要在 _ViewImports.cshtml 中向應用程式註冊。

檢視或下載範例程式碼 \(英文\) (如何下載)

使用案例

兩個常見的標籤協助程式元件的使用案例為:

  1. <link> 插入 <head>
  2. <script> 插入 <body>

下列各節描述這些案例。

插入 HTML 標頭項目

在 HTML <head> 項目中,CSS 檔案一般與 HTML <link> 項目一起匯入。 下列程式碼會使用 head 標籤協助程式元件,將 <link> 項目插入 <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;
        }
    }
}

在上述程式碼中:

  • AddressStyleTagHelperComponent 會實作 TagHelperComponent。 抽象:
    • 允許使用 TagHelperContext 初始化類別。
    • 可讓您使用標籤協助程式元件新增或修改 HTML 項目。
  • Order 屬性會定義元件的轉譯順序。 當應用程式中有多種標籤協助元件用法時,則 Order 為必要。
  • ProcessAsync 會將執行內容的 TagName 屬性值與 head 進行比較。 如果比較評估為 True,則 _style 欄位的內容會插入 HTML <head> 項目。

插入 HTML 本文項目

body 標籤協助程式元件可將 <script> 項目插入 <body> 項目。 下列程式碼示範這項技術:

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

個別的 HTML 檔案用於儲存 <script> 項目。 該 HTML 檔案會使程式碼更簡潔且更容易維護。 上述程式碼會讀取 TagHelpers/Templates/AddressToolTipScript.html 的內容,並將它附加至標籤協助程式輸出。 AddressToolTipScript.html 檔案包含下列標記:

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

上述程式碼會將 啟動程序工具提示小工具繫結至包含 printable 屬性的任何 <address> 項目。 當滑鼠指標停留在項目上時,會顯示效果。

註冊元件

標籤協助程式元件必須新增至應用程式的標籤協助程式元件集合中。 有三種方式可新增至集合:

透過服務容器註冊

如果標籤協助程式元件類別並未以 ITagHelperComponentManager 管理,則必須使用相依性插入 (DI) 系統來註冊。 下列 Startup.ConfigureServices 程式碼會使用暫時性存留期來註冊 AddressStyleTagHelperComponentAddressScriptTagHelperComponent 類別:

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

透過 Razor 檔案註冊

如果標籤協助程式元件未向 DI 註冊,則可以從 Razor Pages 頁面或 MVC 檢視進行註冊。 這項技術用於控制插入的標記和來自 Razor 檔案的元件執行順序。

ITagHelperComponentManager 用於新增標籤協助程式元件,或從應用程式移除。 下列程式碼使用 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));
}

在上述程式碼中:

  • @inject 指示詞會提供 ITagHelperComponentManager 的執行個體。 該執行個體會指派給名為 manager 的變數,以存取 Razor 檔案中的下游。
  • AddressTagHelperComponent 的執行個體會新增至應用程式標籤協助程式元件集合。

AddressTagHelperComponent 已修改,以容納接受 markuporder 參數的建構函式:

private readonly string _markup;

public override int Order { get; }

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

提供的 markup 參數會用於 ProcessAsync,如下所示:

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

透過頁面模型或控制器註冊

如果標籤協助程式元件並未註冊為 DI,則可以從 Razor Pages 模型或 MVC 控制器進行註冊。 這項技術可用於將 C# 邏輯從 Razor 檔案分開。

建構函式插入可用於存取 ITagHelperComponentManager 的執行個體。 標籤協助程式元件會新增至執行個體的標籤協助程式元件集合。 下列 Razor 頁面的頁面模型使用 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));
    }
}

在上述程式碼中:

  • 建構函式插入可用於存取 ITagHelperComponentManager 的執行個體。
  • AddressTagHelperComponent 的執行個體會新增至應用程式標籤協助程式元件集合。

建立元件

建立自訂標籤協助程式元件:

下列程式碼會建立以 <address> 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)
        {
        }
    }
}

使用自訂 address 標籤協助程式元件來插入 HTML 標記,如下所示:

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

上述 ProcessAsync 方法,會將提供給 SetHtmlContent 的 HTML,插入相符的 <address> 項目。 插入發生於:

  • 執行內容的 TagName 屬性值等於 address
  • 對應的 <address> 項目具有 printable 屬性。

例如,當處理下列 <address> 項目時,if 陳述式會評估為 True:

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

其他資源