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

时间:2015-10-03 12:14:06

标签: asp.net-mvc asp.net-core asp.net-core-mvc

我刚刚注意到,如果我有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后:

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

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

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

1 个答案:

答案 0 :(得分:9)

阅读TagHelperRunner类的源代码,我意识到将为同一元素找到的所有标记助手共享相同的TagHelperContextTagHelperOutput,这些将被处理由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;
}

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

  • TagHelperOutput.IsContentModified仅在修改内容时才会返回true(不属于属性或PreElementPreContentPostElementPostContent被修改)

  • TagHelperOutput.PreElement.IsModified以及PreContentPostElementPostContent的类似内容将在修改后返回true。

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

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

最后,如果您必须在同一元素的多个标记帮助程序之间共享一些数据,则可以使用public void RaiseEvent<T>(EventHandler<T> eventToRaise, T args) where T : EventArgs, IXmlConvertable { Log(eventToRaise.Method.Name, args.ToXElement()); ThreadPool.QueueUserWorkItem((e) => eventToRaise(this, args)); } public event EventHandler<ProductLeftEventArgs> ProductLeftEvent = delegate { }; 字典。