【问题标题】:MVC6 TagHelpers with disposableMVC6 TagHelpers 与一次性
【发布时间】:2015-07-22 03:23:38
【问题描述】:

在较旧的 MVC HTML 帮助程序中,可以使用 IDisposable 包装内容 - 例如,BeginForm 帮助程序会自动包装 *stuff* 并使用结束 form 标记

<% using (Html.BeginForm()) {%>
   *stuff*
<% } %> 

MVC6 TagHelpers 是否支持这种内容包装? 例如我想要这个

<widget-box title="My Title">Yay for content!</widget-box>

被扩展成一个带有包装 div 的引导小部件框:

<div class="widget-box">
    <div class="widget-header">
        <h4 class="widget-title">My Title</h4>
    </div>
    <div class="widget-body">
        <div class="widget-main">
            Yay for content!
        </div>
    </div>
</div>

TagHelpers 可以做到这一点吗?

解决方案:我已将@DanielJG 的答案烘焙到消耗WidgetBoxTagHelper.csworking demo on github 中(与在我的生产应用程序中使用lib 一样,将与Beta/RC/RTM 保持同步)

【问题讨论】:

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


    【解决方案1】:

    标签助手必须实现接口ITagHelper(正如@NTaylorMullen所指出的,TagHelper 类只是实现它时可以使用的便利类),这迫使您使用方法ProcessProcessAsync,因此您不能依赖在Dispose 方法中添加内容。

    但是,您可以完全控制输出内容,因此您可以根据需要替换/修改它。例如,您的小部件标签助手的快速近似(使用 1.0 版本的框架):

    [HtmlTargetElement("widget-box")]
    public class WidgetTagHelper : TagHelper
    {
        public string Title { get; set; }
    
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var outerTag = new TagBuilder("div");
            outerTag.Attributes.Add("class", output.TagName);
            output.MergeAttributes(outerTag);
            output.TagName = outerTag.TagName;
    
            //Create the header
            var header = new TagBuilder("div");
            header.Attributes.Add("class", "widget-header");
            header.InnerHtml.Append(this.Title);
            output.PreContent.SetHtmlContent(header);
    
            //Create the body and replace original tag helper content
            var body = new TagBuilder("div");
            body.Attributes.Add("class", "widget-body");
            var originalContents = await output.GetChildContentAsync();
            body.InnerHtml.Append(originalContents.GetContent());
            output.Content.SetHtmlContent(body);
        }
    }
    

    在您的剃须刀中,您将拥有:

    <widget-box title="My Title">Yay for content!</widget-box>
    

    将呈现为:

    <div class="widget-box">
        <div class="widget-header">My Title</div>
        <div class="widget-body">Yay for content!</div>
    </div>
    

    不要忘记通过在 _ViewImports.cshtml 文件中添加 @addTagHelper 指令来在程序集中注册标签助手。例如,这将在我的应用程序中注册所有助手:

    @addTagHelper *, WebApplication2
    

    旧 beta7 代码

    • 在 beta7 中,您必须使用 [TargetElement] 属性。
    • TagBuilder 类有一个SetInnerText 方法,您可以使用它来将其上下文设置为文本。

    代码看起来像:

    [TargetElement("widget-box")]
    public class WidgetTagHelper : TagHelper
    {
        private IHtmlEncoder encoder;
        public WidgetTagHelper(IHtmlEncoder encoder)
        {
            this.encoder = encoder;
        }
    
        public string Title { get; set; }
    
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var outerTag = new TagBuilder("div");
            outerTag.Attributes.Add("class", output.TagName);
            output.MergeAttributes(outerTag);
            output.TagName = outerTag.TagName;
    
            //Create the header
            var header = new TagBuilder("div");
            header.Attributes.Add("class", "widget-header");
            header.SetInnerText(this.Title);
            output.PreContent.SetContent(header);
    
            //Create the body and replace original tag helper content
            var body = new TagBuilder("div");
            body.Attributes.Add("class", "widget-body");
            var originalContents = await context.GetChildContentAsync();           
            using (var writer = new StringWriter())
            {
                body.TagRenderMode = TagRenderMode.StartTag;
                body.WriteTo(writer, encoder);
                originalContents.WriteTo(writer, encoder);
                body.TagRenderMode = TagRenderMode.EndTag;
                body.WriteTo(writer, encoder);
                output.Content.SetContent(writer.ToString());
            }                            
        }
    }
    

    旧 beta5 代码

    • 标签助手中有一个InnerHtml 属性。
    • 标签助手中有一个ToHtmlString 方法用于将它们呈现为html。

    代码看起来像:

    [TargetElement("widget-box")]
    public class WidgetTagHelper: TagHelper
    {
        public string Title { get; set; }
    
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var outerTag = new TagBuilder("div");
            outerTag.Attributes.Add("class", output.TagName);
            output.MergeAttributes(outerTag);
            output.TagName = outerTag.TagName;
    
            //Create the header
            var header = new TagBuilder("div");
            header.Attributes.Add("class", "widget-header");
            header.InnerHtml = this.Title;
            output.PreContent.SetContent(header.ToHtmlString(TagRenderMode.Normal).ToString());
    
            //Create the body and replace original tag helper content
            var body = new TagBuilder("div");
            body.Attributes.Add("class", "widget-body");
            var originalContents = await context.GetChildContentAsync();
            body.InnerHtml = originalContents.GetContent();
            output.Content.SetContent(body.ToHtmlString(TagRenderMode.Normal).ToString());
        }
    }
    

    【讨论】:

    • 不客气@fiat。玩asp .net 5 很有趣:)。顺便说一句,我刚刚看到你的 github 仓库,好主意!
    • 额外说明:要成为有效的TagHelper,您只需实现ITagHelper 接口。 TagHelper 类只是一个很好的基础实现:)
    • 在 BETA 8 TagBuilder 中不再有 SetInnerText 方法,因此代码不起作用。你只会得到内文
    • @firste,我终于有时间试用 RC1 版本的 ASP 5 并更新代码
    猜你喜欢
    • 2015-02-06
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 2017-01-03
    • 1970-01-01
    相关资源
    最近更新 更多