Asp.net-Mvc

針對同一元素的多個標籤助手

  • December 10, 2019

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

如果此幫助器在預設 ASP之後在 _ViewImports.cshtml 中註冊:

  • 每當Process被呼叫時,TagHelperOutput已經包含了預設生成的hrefAnchorTagHelper。我還可以以我喜歡的任何方式更新預設標籤助手生成的錨點。

對這種行為有任何程度的控制嗎?

您可能想要決定是否執行針對同一元素的更多幫助程序(就像密封您的輸出一樣)。您可能還希望允許其他助手,但請確保未修改某些屬性。

覆蓋只讀屬性順序,如下所示:

[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該類的原始碼,我意識到對於為同一元素找到的所有標籤助手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(而不是在屬性或PreElement, PreContent, PostElement,PostContent被修改時)
  • TagHelperOutput.PreElement.IsModified和 , 類似PreContentPostElement並且PostContent在修改後將返回 true。
  • 前一個標籤助手設置的內容可以通過呼叫TagHelperOutput.Content.Clear()Pre/Post Element/Context 屬性的類似方法來刪除。
  • TagHelperOutput.SuppressOutput()可以通過在每個屬性上呼叫 clear 並將 TagName 設置為 null來完全抑制內容。如果您希望標籤助手渲染某些內容,則需要再次分配它們。

最後,如果您必須在同一元素的多個標籤助手之間共享一些數據,您可以使用TagHelperContext.Items字典。

引用自:https://stackoverflow.com/questions/32922425