Адаптация пользовательского HTML-хелпера для бритвы (использует HTMLTextWriter, поэтому возвращает пустоту)
-
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("");
}
Но это немного взлома.