如何创建包含其他标签助手的自定义标签助手

How to create custom tag helper containing other tag helpers

public class FormControlTextBoxHelper:TagHelper
{

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        using (var writer = new StringWriter())
        {
            writer.Write(@"<div class=""form-group"">");

            //Here I want to write <label asp-for="InputModel.Title" class="control-label"></label> and other tag helpers

            writer.Write(@"</div>");

            output.Content.SetHtmlContent(writer.ToString());

        }

    }
}

我在 1-2 小时内找不到有关如何拥有包含其他标签助手的自定义标签助手的任何信息。 Microsoft docs 显示了非常简单的示例,其中不包含很多有意义的信息。

我在阅读了多篇不同的文章后找到了答案。

所以首先你需要在标签助手IHtmlGenerator的构造函数中注入,这将生成标签助手html,同时元素的生成需要ViewContext,你只能拥有有 属性 和 Attribute ViewContext

这是 ViewContext 属性的摘要:

Summary:

Specifies that a tag helper property should be set with the current Microsoft.AspNetCore.Mvc.Rendering.ViewContext when creating the tag helper. The property must have a public set method.

代码如下所示:

[HtmlTargetElement("form-control-text-box")]
public class FormControlTextBoxHelper:TagHelper
{
    [HtmlAttributeName("asp-for")]
    public ModelExpression For { get; set; }

    private readonly IHtmlGenerator _generator;

    [ViewContext]
    public ViewContext ViewContext { get; set; }

    public FormControlTextBoxHelper(IHtmlGenerator generator)
    {
        _generator = generator;
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        using (var writer = new StringWriter())
        {
            writer.Write(@"<div class=""form-group"">");

            var label = _generator.GenerateLabel(
                            ViewContext, 
                            For.ModelExplorer, 
                            For.Name, null, 
                            new { @class = "control-label" });

            label.WriteTo(writer, NullHtmlEncoder.Default);

            var textArea = _generator.GenerateTextBox(ViewContext, 
                                For.ModelExplorer, 
                                For.Name, 
                                For.Model, 
                                null, 
                                new { @class = "form-control" });

            textArea.WriteTo(writer, NullHtmlEncoder.Default);

            var validationMsg = _generator.GenerateValidationMessage(           
                                    ViewContext, 
                                    For.ModelExplorer, 
                                    For.Name, 
                                    null, 
                                    ViewContext.ValidationMessageElement, 
                                    new { @class = "text-danger" });

            validationMsg.WriteTo(writer, NullHtmlEncoder.Default);

            writer.Write(@"</div>");

            output.Content.SetHtmlContent(writer.ToString());

        }

    }
}

所以这个像 <form-control-text-box asp-for="InputModel.Title"></form-control-text-box> 这样调用的标签助手将产生 html 等于:

<div class="form-group">
    <label asp-for="InputModel.Title" class="control-label"></label>
    <input asp-for="InputModel.Title" class="form-control" />
    <span asp-validation-for="InputModel.Title" class="text-danger"></span>
</div>

我希望我能帮助别人更快地解决这个问题。