TagHelper通过调用GetChildContentAsync()和Content.GetContent()

时间:2016-07-11 15:02:03

标签: caching asp.net-core-mvc tag-helpers

根据this article,如果我们使用多个标记帮助程序(针对相同的标记),并且在每个标记帮助程序中,我们将使用await output.GetChildContentAsync()来接收html内容,我们将通过缓存输出来解决问题:

  

问题是标记帮助器输出是高速缓存的,当运行WWW标记助手时,它会覆盖HTTP标记助手的高速缓存输出。

使用如下语句修复问题:

   var childContent = output.Content.IsModified ? output.Content.GetContent() : 
                (await output.GetChildContentAsync()).GetContent();

此行为的描述:

  

上面的代码检查内容是否已被修改,以及是否   它有,它从输出缓冲区获取内容。

问题是:
1)引擎盖下TagHelperOutput.GetChildContentAsync()TagHelperOutput.Content.GetContent()之间有什么区别? 2)哪种方法将结果写入缓冲区?
3)它是什么意思"缓存输出":ASP.NET MVC Core缓存TagHelper调用后的初始剃刀标记或html标记?

提前感谢!

2 个答案:

答案 0 :(得分:1)

经过一些源代码分析后,我得到了答案:
区别在于:
  - 方法TagHelperOutput.GetChildContentAsync()执行子TagHelpers并将结果生成为TagHelperContent。从这个对象我们可以接收html标记作为调用内部TagHelpers的结果,并进一步使用它作为当前TagHelper结果。此方法还缓存呈现内部TagHelperContents的子Tasks
在同一元素的范围内调用此方法将产生相同的结果(来自缓存)。
  - 方法TagHelperOutput.Content.GetContent()从调用TagHelperOutput.GetChildContentAsync()的缓冲结果中返回html标记。这意味着,如果我们未在第一个TagHelper中调用TagHelperOutput.GetChildContentAsync()方法,则会收到string.Empty结果。

代码示例:
1)此助手将产生string.Empty结果,因为TagHelperOutput.GetChildContentAsync()未被调用:

 [HtmlTargetElement("p")]
    public class AutoLinkerHttpTagHelper : TagHelper
    {
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var childContent = output.Content.GetContent();

            output.Content.SetHtmlContent(Regex.Replace(
                childContent,
                @"\b(?:https?://)(\S+)\b",
                "<a target=\"_blank\" href=\"$0\">$0</a>"
            ));
        }
    }

    [HtmlTargetElement("p")]
    public class AutoLinkerWwwTagHelper : TagHelper
    {
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var childContentBySync = output.Content.GetContent();

            output.Content.SetHtmlContent(Regex.Replace(
                childContentBySync,
                 @"\b(www\.)(\S+)\b",
                 "<a target=\"_blank\" href=\"http://$0\">$0</a>"));
        }
    }

2)如果我们改变第一个帮助器的ProcessAsync方法,那么:

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        var childContent = (await output.GetChildContentAsync()).GetContent();

        output.Content.SetHtmlContent(Regex.Replace(
            childContent,
            @"\b(?:https?://)(\S+)\b",
            "<a target=\"_blank\" href=\"$0\">$0</a>"
        ));
    }

结果没问题。

这是输出结果的一些保险:

var childContent = output.Content.IsModified ? output.Content.GetContent() : 
        (await output.GetChildContentAsync()).GetContent();

换句话说,我们检查是否调用了GetChildContentAsync()

希望它会对某人有所帮助。

答案 1 :(得分:0)

其他答案的解释对我来说还不清楚,因此我对其进行了测试,以下是摘要:

  • await output.GetChildContentAsync(); =>获取标记内的原始内容,该内容在Razor文件中进行了硬编码。请注意,它将在第一次调用时被缓存,并且在以后的调用中永远不会更改,因此它不会反映其他TagHelpers在运行时所做的更改!

  • output.Content.GetContent(); =>仅应用于获取由某些TagHelper修改的内容,否则将返回Empty!

用法样本:

获取最新内容(无论是初始剃刀还是其他标签助手修改的内容):

var curContent = output.IsContentModified ? output.Content : await output.GetChildContentAsync();
string strContent = curContent.GetContent();