【问题标题】:TagBuilder InnerHtml in ASP.NET 5 MVC 6ASP.NET 5 MVC 6 中的 TagBuilder InnerHtml
【发布时间】:2015-09-05 18:32:11
【问题描述】:

在我看来,从 beta7 开始,TagBuilder 发生了重大的重大变化,而公告存储库中没有提及它们。

特别是 .ToString 不再呈现标签生成器,它只是返回类型的名称。 以前我们可以在 HtmlHelper 扩展中做这样的事情来构建嵌套的 html 元素:

var li = new TagBuilder("li");
li.AddCssClass("inactive");
var span = new TagBuilder("span");
span.SetInnerText(somestring);
li.InnerHtml = span.ToString();

.InnerHtml 现在不再接受字符串,因为它现在是 IHtmlContent

但由于 .ToString() 不呈现标签,这也不起作用:

li.InnerHtml = new HtmlString(span.ToString())

它只是呈现为“Microsoft.AspNet.Mvc.Rendering.TagBuilder”,即类型的名称。

我没有在 TagBuilder 上看到任何提供所需功能的新方法。 我错过了什么?我现在如何使用 TagBuilder 构建复杂的嵌套 html?

【问题讨论】:

  • TagBuilder 实现 IHtmlContent 所以也许你可以直接将 TagBuilder 分配给 li.InnerHtml

标签: c# asp.net-mvc asp.net-core asp.net-core-mvc


【解决方案1】:

使用 MVC 6,在撰写本文时,Tagbuiler.InnerHtml 确实不再有 setter。它有一些方法来附加元素。例如你可以写:

var container = new TagBuilder("div");
var input = new TagBuilder("input");

container.InnerHtml.AppendHtml(input);

【讨论】:

    【解决方案2】:

    因为TagBuilder现在实现了IHtmlContent,你应该可以直接使用它,不用做.ToString()

    var li = new TagBuilder("li");
    li.AddCssClass("inactive");
    var span = new TagBuilder("span");
    span.SetInnerText(somestring);
    li.InnerHtml = span;
    

    Beta 7 中当前实现的真正问题是没有简单的方法将两个子标签构建器内容附加到父标签构建器内容。可以关注GitHub的讨论。

    目前的提议是让InnerHtml 不可分配,而是支持Append。这将在 Beta 8 中实施。

    Beta 7 中的解决方法是使用 StringWriter 调用 parent.WriteTo 以将其转换为 string

    【讨论】:

    • 我会说真正的问题是在自定义 HtmlHelper 方法中使用 TagBuilder.ToString() 的大量 MVC3+ 代码现在完全被破坏了。想要从一个构建 HTML 字符串的类中获取一个 HTML 字符串是不是很激进?
    • MVC 6 与 MVC 5 及之前的版本完全不同。向后兼容性从来都不是优先事项。这种差异与 WebForms 和 MVC 之间的差异相当(夸大其词 - 我知道)。您不会看到很多项目被迁移。 MVC 6 更针对新项目和完成返工。
    • 我很欣赏这一点,但我怀疑这些github.com/…✓ 中的许多人在迁移他们的可重用组件代码时会感到非常震惊,并且它会默默地失败。 ToString() 的实现违反了最小意外原则,并且无缘无故地使迁移变得更加困难(除了“我们认为人们不应该这样做”)。
    【解决方案3】:

    失去了span.SetInnerText(somestring); 现在可以做

    span.InnerHtml.SetContent(somestring);

    使用Microsoft.AspNetCore.Html.HtmlContentBuilderExtensions

    这是从带有 AspNetCore 2.0.1 的 4.7 的角度来看的。

    【讨论】:

      【解决方案4】:

      @Memet 奥尔森

      我所有的自定义 TagHelpers 都因更新到 4.6.1 (1.0.0-rc2) 而中断。 InnerHtml.Append() 将不再接受 TagBuilder。

      应该使用 AppendHtml() 方法:

      var container = new TagBuilder("div");
      var input = new TagBuilder("input");
      
      container.InnerHtml.AppendHtml(input);
      

      第二次错误修复[here]

      【讨论】:

        【解决方案5】:

        以@Mihai 的回答为基础,展示 StringWriter 方法的实际代码:

        // Create tag builder
        var builder = new TagBuilder("img");
        //...
        // Render tag approach also changed in .NetCore
        builder.TagRenderMode = TagRenderMode.SelfClosing;
        
        //Create the StringWriter and make TagBuilder "WriteTo" it
        var stringWriter = new System.IO.StringWriter();
        builder.WriteTo(stringWriter, HtmlEncoder.Default);
        var tagBuilderIsFinallyAStringNow = stringWriter.ToString();
        

        【讨论】:

          【解决方案6】:

          Beta 8 通过向标签助手添加 Append() 方法解决了这个问题。

          对于 beta 7,解决方案是使用 BufferedHtmlContent() 类,但由于它不可访问,我们必须做一些额外的工作。

          private class MyBufferedHtmlContent : IHtmlContent
          {
              internal List<IHtmlContent> Entries { get; } = new List<IHtmlContent>();
          
              public MyBufferedHtmlContent Append(IHtmlContent htmlContent)
              {
                  Entries.Add(htmlContent);
                  return this;
              }
          
              public void WriteTo(TextWriter writer, IHtmlEncoder encoder)
              {
                  foreach (var entry in Entries)
                  {
                      entry.WriteTo(writer, encoder);
                  }
              }
          }
          

          用法:

          TagBuilder firstChild = new TagBuilder("input");
          firstChild.MergeAttribute("type", "hidden");
          firstChild.MergeAttribute("name", "Ids");
          firstChild.TagRenderMode = TagRenderMode.SelfClosing;
          
          TagBuilder secondChild = new TagBuilder("input");
          secondChild.MergeAttribute("type", "hidden");
          secondChild.MergeAttribute("name", "Ids");
          secondChild.TagRenderMode = TagRenderMode.SelfClosing;
          
          var innerHtml = new MyBufferedHtmlContent();
          innerHtml.Append(firstChild);
          innerHtml.Append(secondChild);
          TagBuilder parent = new TagBuilder("div");
          parent.InnerHtml = innerHtml;
          

          【讨论】:

          • 检查您的测试版。这是针对 Beta 7 的。
          猜你喜欢
          • 1970-01-01
          • 2016-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-24
          • 1970-01-01
          相关资源
          最近更新 更多