Адаптация пользовательского HTML-хелпера для бритвы (использует HTMLTextWriter, поэтому возвращает пустоту)

StackOverflow https://stackoverflow.com/questions/4217611

  •  26-09-2019
  •  | 
  •  

Вопрос

Эта проблема

У меня есть очень нефте-медленное меню HTML Helper, написанное для видов WebFormViewEngine. Этот двигатель позволяет вашим помощникам вернуть пустоту и все же можно использовать:

@Html.Theseus

Это отлично подходит для моего помощника, потому что он может затем сделать меню, используя HTMLTextWriter, который отображается непосредственно на выходной поток.

Однако в видах бритве, однако, помогители HTML должны вернуть значение (обычно MVCHTMLSTRING), который является то, что добавляется к выходу. Небольшая разница, большие последствия.

Вокруг этого есть путь, как указал на меня GVS (см. ASP.NET MVC 2 до MVC 3: пользовательские помощники HTML в бритве) следующим образом:

Если помощник возвращает пустоту, то сделайте следующее:

@{Html.Theseus;}

(По сути, вы просто называете метод, а не рендурируете в виду).

В то время как все еще аккуратно, это не совсем так, как @ html.thesus. Так...

Мой код сложен, но очень хорошо работает, так как угодно, чтобы пройти через основные изменения, то есть, заменяя HTMLTextWriter с другим писателем. Снаппин кода идет:

writer.AddAttribute(HtmlTextWriterAttribute.Href, n.Url);
writer.AddAttribute(HtmlTextWriterAttribute.Title, n.Description);
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.WriteEncodedText(n.Title);
writer.RenderEndTag();

// Recursion, if any
// Snip off the recursion at this level if specified by depth
// Use a negative value for depth if you want to render the entire sitemap from the starting node

    if ((currentDepth < depth) || (depth < 0))
    {
         if (hasChildNodes)
         {
              // Recursive building starts here

              // Open new ul tag for the child nodes 
              // "<ul class='ChildNodesContainer {0} Level{1}'>"; 
              writer.AddAttribute(HtmlTextWriterAttribute.Class, "Level" + currentDepth.ToString());
              writer.RenderBeginTag(HtmlTextWriterTag.Ul);

              // BuildMenuLevel calls itself here to 
              // recursively traverse the sitemap hierarchy, 
              // building the menu as I go.
              // Note: this is where I increase the currentDepth variable!
               BuildChildMenu(currentDepth + 1, depth, n, writer);

              // Close ul tag for the child nodes
              writer.RenderEndTag();
          }
    }

Было бы не забавно написать с помощью тацберторов. Как он стоит, он оказывает любой тип меню, включая «инкрементную навигацию», как описано в моей статье 4GUYSFROMROLL:Реализация инкрементной навигации с ASP.NET

Варианты:

Я думаю, я мог бы вернуть пустую mvchtmlstring, но это в значительной степени определение взлома ...

Единственная альтернатива - отправиться в закат и переписать помощника, используя TagBuilder, чтобы построить каждый тег, добавить это в StringBuilder, затем построить следующий тег и т. Д., а затем использовать экземпляр stringBuilder для создания mvchtmlstring. Серьезно безобразно, если я не мог сделать что-то вроде ...

Вопрос:

Есть ли способ:

Остановите рендурирование HTMLTextWriter к потоку и вместо этого используйте его как StringBuilder, что в конце процесса я использую для создания MVCHTMLSTRING (или HTMLSTRING)?

Звучит маловероятно, даже как я пишу ...

PS:

Великая вещь о HTMLTextWriter - это то, что вы можете строить большие количества тегов, вместо того, чтобы построить их по одному, как с талком.

Это было полезно?

Решение

Вопреки ответам, которые вы получили для вашего другой вопрос Бритва не требует, чтобы вы вернули HTMLSTRING. Проблема с вашим кодом прямо сейчас в том, что вы пишете напрямую к потоку ответа. Бритвы выполняет вещи наизнанку, что означает, что вы можете испортить порядок ответа (см. Подобный вопрос).

Так что в вашем случае вы можете сделать это (хотя я не проверил его):

public static void Theseus(this HtmlHelper html)
{
    var writer = new HtmlTextWriter(html.ViewContext.Writer);
    ...
}

Редактировать (Следите за решению ваших комментариев):

HTML помощники идеально способны либо возвращать HTMLSTRING напрямую или недействителен и писать в контекстный писатель. Например, оба Html.Partial а также Html.RenderPartial работать нормально в бритве. Я думаю, что вы запутаете, это синтаксис требуется позвонить одну версию, а не другую.

Например, рассмотрим вид ASPX:

<%: Html.Partial("Name") %>
<% Html.RenderPartial("Name") %>

Вы называете каждый метод по-разному. Если вы переверните вещи, вещи просто не будут работать. Точно так же в бритве:

@Html.Partial("Name")
@{ Html.RenderPartial("Name"); }

Теперь он просто так бывает, что синтаксис использовал пустотный хелпер намного более многословным в бритве по сравнению с ASPX. Однако оба работают просто хорошо. Если вы не имеете в виду что-то еще «проблемой, с HTML-помощником не сможет вернуть пустоту».

Кстати, если вы действительно хотите позвонить вашему помощнику, используя этот синтаксис: @Html.Theseus() Вы могли бы сделать это:

public static IHtmlString Theseus(this HtmlHelper html)
{
    var writer = new HtmlTextWriter(html.ViewContext.Writer);
    ...
    return new HtmlString("");
}

Но это немного взлома.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top