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

Dan*_*.G. 5 asp.net-mvc asp.net-core-mvc asp.net-core

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

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

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

        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

使用如下(注意我也添加了默认锚点助手的属性asp-controller):

<a class="menu" asp-controller="Home" asp-action="Index" foo>Foo</a>
Run Code Online (Sandbox Code Playgroud)

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

  • 每当Process调用时,TagHelperOutput已经包含默认生成的hrefAnchorTagHelper.我也可以用我喜欢的任何方式更新默认标签助手生成的锚点.

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

您可能想要决定是否执行针对同一元素的其他帮助程序(如同密封输出一样).您可能还希望允许其他帮助程序,但请确保未修改某些属性.

Dan*_*.G. 9

阅读TagHelperRunner该类的源代码,我意识到同样的TagHelperContext,TagHelperOutput并将为所有为同一元素找到的标记助手共享,这些助手将由ITagHelper.Order属性处理.

因此,您可以通过为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;
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我还发现您可以查询一些属性TagHelperOutput以检查先前的标记助手是否已修改输出.虽然您无法知道具有更高顺序的标签助手(在您之后执行)是否会修改输出:

  • TagHelperOutput.IsContentModified将返回true,只有当内容被修改(而不是当属性或PreElement,PreContent,PostElement,PostContent被修改)

  • TagHelperOutput.PreElement.IsModified和类似的PreContent,PostElement并将PostContent在修改后返回true.

  • 可以通过调用TagHelperOutput.Content.Clear()以及类似的Pre/Post Element/Context属性来删除由先前标记帮助程序设置的内容.

  • 通过调用TagHelperOutput.SuppressOutput()每个属性上的哪些调用清除并将TagName设置为null,可以完全抑制内容.如果您希望标记帮助器呈现某些内容,则需要再次分配它们.

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