标记助手执行顺序 [英] Tag helper order of execution

查看:110
本文介绍了标记助手执行顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一组ASP.Net Core标记辅助对象,这些辅助对象的目标是(以及其他标记)< form> < input> 标签。我的< form> 标签助手定义了一个自定义属性,该属性的值希望传递给子元素。



我读过的所有文章都听起来很简单:父标记助手将值存储在 context.Items 字典中,孩子们从中读取该值。



这意味着子标记助手在父标记助手之后执行。但是,我发现这种情况< form> &input; 标记助手中的 FormTagHelper InputTagHelper 之后执行



通过示例,考虑此HTML:

 < form my-attr ='Hello'> 
< input asp-for = SomeProperty />
< / form>

我的表单标签助手:

 公共类FormTagHelper:TagHelper 
{
公共字符串MyAttr {get;组; }
公共重写void Process(TagHelperContext上下文,TagHelperOutput输出)
{
Debug.WriteLine(< form>));
context.Items.Add( my-attr,MyAttr ??);
}
}

输入标签助手:

 公共类InputTagHelper:TagHelper 
{
公共重写void Process(TagHelperContext上下文,TagHelperOutput输出)
{
Debug.WriteLine(< input>);
var valueFromParentForm = context.Items [ my-attr]。ToString();
}
}

我希望 valueFromParentForm Hello ,但实际上它会引发异常,因为context.Items字典为空。



这是什么一回事,我应该怎么做才能解决这个奇怪的,由内而外的执行顺序?

解决方案

解决方案



除了



我认为执行顺序是不言而喻的。但是红色的无法访问部分呢?首先,我们来确定 Items 词典的确切含义以及其工作方式。它以 IDictionary< object,object> 表示,但它不是常规词典。这是



这是因为 InputTagHelper 的值已添加到 _innerDictionary 而不是 _sourceDictionary ,然后在 FormTagHelper 中使用。这种行为会创建对 Items 词典的单向访问。儿童标签助手可以访问父母添加的值,但不是相反。



项目的状态词典在执行 InputTagHelper() Init()方法后:




I am writing a set of ASP.Net Core tag helpers that target (among other tags) <form> and <input> tags. My <form> tag helper defines a custom attribute, the value of which it wants to pass to the child elements.

All of the articles I've read make this sound simple: The parent tag helper stores the value in the context.Items dictionary, and the children read it from that same dictionary.

This implies that the child tag helpers execute after the parent tag helper. However, I've discovered that, in the case of <form> and <input> tag helpers, the FormTagHelper executes after the InputTagHelper.

By way of example, consider this HTML:

<form my-attr='Hello'>
  <input asp-for='SomeProperty' />
</form>

My form tag helper:

public class FormTagHelper : TagHelper
{
    public string MyAttr { get; set; }
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        Debug.WriteLine("<form>");
        context.Items.Add("my-attr", MyAttr ?? "");
    }
}

Input tag helper:

public class InputTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        Debug.WriteLine("<input>");
        var valueFromParentForm = context.Items["my-attr"].ToString();
    }
}

I would expect valueFromParentForm to be "Hello", but in fact it throws an exception because the context.Items dictionary is empty.

What is this is all about, and what might I do to work around this weird, inside-out order of execution?

解决方案

Solution

Aside for Process() method the base tag helper provides also Init() method. It's summary:

Initializes the Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper with the given context. Additions to Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext.Items should be done within this method to ensure they're added prior to executing the children.

Simply override this method and add whatever you need:

public override void Init(TagHelperContext context)
{
    context.Items.Add(1, "Init FormTagHelper");
}


Explanation

For your html code:

<form my-attr='Hello'>
  <input asp-for='SomeProperty' />
</form>

let's have two tag helpers:

FormTagHelper

[HtmlTargetElement("form")]
public class FormTagHelper : TagHelper
{
    public override void Init(TagHelperContext context)
    {
        context.Items.Add(1, "Init FormTagHelper");
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        context.Items.Add(4, "Process FormTagHelper");
    }
}

InputTagHelper

[HtmlTargetElement("input")]
public class InputTagHelper : TagHelper
{
    public override void Init(TagHelperContext context)
    {
        context.Items.Add(2, "Init InputTagHelper");
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        context.Items.Add(3, "Process InputTagHelper");
    }
}

To understand better in what order methods are called let's take a look at this diagram:

I think the execution order is pretty self-explanatory. But what about the red No access part? Let's starts with establishing what exactly Items dictionary is and how it works. It figures as IDictionary<object, object> but it is not a regular dictionary. It's a CopyOnWriteDictionary and it is quite special. It has two underlying dictionaries ReadDictionary and WriteDictionary and it calls either of them depending on what type of action (read/write) is currently performed.

While you can add 1 from FormTagHelper.Init(), you won't be able to access keys 2 and 3 from FormTagHelper.Process() despite the fact that according to the diagram they should already be there:

That's because values for InputTagHelper are being add to _innerDictionary not _sourceDictionary which is then used in FormTagHelper. Such behaviour creates one-way access to Items dictionary. Children tag helpers are able to access values added by parents, but not the opposite way.

State of Items dictionary after execution of Init() method of InputTagHelper():

这篇关于标记助手执行顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆