针对同一元素的多个标签助手

Multiple tag helpers targetting the same element

我刚刚注意到,如果我有 2 个标记助手针对同一个元素,则都可以执行。它们执行的顺序取决于它们在_ViewImports.cshtml.

中注册的顺序

例如,我可以为锚元素创建另一个标签助手:

[HtmlTargetElement("a", Attributes = "foo")]
public class FooTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        //Get the url from href attribute generated in the default AnchorTagHelper
        var url = output.Attributes["href"].Value.ToString();

        ...
    }
}

按如下方式使用它(注意我还添加了默认锚助手的属性,如 asp-controller):

<a class="menu" asp-controller="Home" asp-action="Index" foo>Foo</a>

如果此助手在 _ViewImports.cshtml 之后 默认 ASP 注册:

对这种行为有任何程度的控制吗?

您可能想决定是否针对同一元素执行进一步的帮助程序(就好像 密封 您的输出)。您可能还想允许其他助手,但请确保未修改某些属性。

覆盖只读的属性命令,像这样:

[HtmlTargetElement("a", Attributes = "foo")]
public class FooTagHelper : TagHelper
{
    // This should be the last tag helper on any tag to run
    public override int Order => int.MaxValue;

    public override async Task ProcessAsync(TagHelperContext context,
        TagHelperOutput output)
    {
        //...
    }
}

阅读 TagHelperRunner class 的源代码,我意识到相同的 TagHelperContextTagHelperOutput 将被所有找到的标签助手共享元素,将按 ITagHelper.Order 属性.

顺序处理

因此您可以通过为订单分配适当的值来控制它们的执行顺序 属性。作为参考,这是 TagHaelperRunner.RunAsync 方法:

public async Task<TagHelperOutput> RunAsync([NotNull] TagHelperExecutionContext executionContext)
{
    var tagHelperContext = new TagHelperContext(
        executionContext.AllAttributes,
        executionContext.Items,
        executionContext.UniqueId,
        executionContext.GetChildContentAsync);
    var tagHelperOutput = new TagHelperOutput(
        executionContext.TagName,
        executionContext.HTMLAttributes)
    {
        SelfClosing = executionContext.SelfClosing,
    };
    var orderedTagHelpers = executionContext.TagHelpers.OrderBy(tagHelper => tagHelper.Order);

    foreach (var tagHelper in orderedTagHelpers)
    {
        await tagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);
    }

    return tagHelperOutput;
}

到目前为止,我还发现您可以查询 TagHelperOutput 中的一些属性来检查以前的标签助手是否修改了输出。尽管您不知道是否有更高阶的标签助手(在您之后执行)修改了输出:

  • TagHelperOutput.IsContentModified 仅当内容被修改时才会 return 为真(当属性或 PreElementPreContentPostElement, PostContent被修改)

  • TagHelperOutput.PreElement.IsModified 以及 PreContentPostElementPostContent 的类似内容将 return 在修改后为真。

  • 可以通过调用 TagHelperOutput.Content.Clear() 和类似的 Pre/Post Element/Context 属性来删除之前标记助手设置的内容。

  • 可以通过调用 TagHelperOutput.SuppressOutput() 来完全抑制内容,它会在每个属性上调用 clear 并将 TagName 设置为 null。如果您希望标签助手呈现某些内容,则需要再次分配它们。

最后,如果您必须在同一个元素的多个标签助手之间共享一些数据,您可以使用 TagHelperContext.Items 字典。