TagBuilder InnerHtml в ASP.NET 5 MVC 6

Мне кажется, что в TagBuilder есть серьезные изменения в отношении бета-версии 7 без упоминания о них в репортажах объявлений.

В частности. ToString больше не создает tagbuilder, он просто возвращает имя типа. ранее мы могли бы делать такие вещи внутри наших расширений 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 для обеспечения необходимой функциональности. Что мне не хватает? Как я могу теперь построить сложный вложенный html с TagBuilder?

Ответы

Ответ 1

Поскольку 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. Это предназначено для реализации в Бета 8.

Обходной путь в Бета 7 состоит в вызове parent.WriteTo с StringWriter, чтобы преобразовать его в string.

Ответ 2

Используя MVC 6, на момент написания, Tagbuiler.InnerHtml больше не имеет сеттера. У этого есть некоторые методы, чтобы добавить элемент. Например, вы могли бы написать:

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

container.InnerHtml.AppendHtml(input);

Ответ 3

Бета-версия 8 решила эту проблему, добавив метод Append() для тегов-помощников.

Для бета-версии 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;

Ответ 4

@Memet Olsen

Все мои собственные 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);

2nd bug-fix [здесь]

Ответ 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();