gpt4 book ai didi

asp.net-mvc - 为 Razor 调整自定义 Html Helper(它使用 HtmlTextWriter,因此返回 void)

转载 作者:行者123 更新时间:2023-12-01 10:12:14 25 4
gpt4 key购买 nike

问题

我有一个非常漂亮的菜单 Html 帮助程序,它是为 WebFormViewEngine View 编写的。该引擎允许您的助手返回 void,并且仍然能够使用:

@Html.Theseus

这对我的助手来说很棒,因为它可以使用 HtmlTextWriter 渲染菜单,直接渲染到输出流。

然而,在 Razor View 中,Html 帮助程序应该返回一个值(通常是 MvcHtmlString),该值将被添加到输出中。小差异,大后果。

正如 GvS(参见 ASP.NET MVC 2 to MVC 3: Custom Html Helpers in Razor)向我指出的那样,有一种解决方法如下:

如果助手返回 void,则执行以下操作:

@{Html.Theseus;}

(本质上,您只是调用方法,而不是渲染到 View 中)。

虽然仍然很整洁,但这与@Html.Theseus 不太一样。所以……

我的代码很复杂但运行良好,所以我不愿意进行重大编辑,即用另一个编写器替换 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();
}
}

用 TagBuilders 重新编写不会很有趣。就目前而言,它呈现任何类型的菜单,包括我在 4guysfromrolla 文章中描述的“增量导航”: Implementing Incremental Navigation with ASP.NET

选项:

我想我可以返回一个空的 MvcHtmlString,但这几乎就是 hack 的定义......

唯一的选择是走向日落,使用 TagBuilder 重写帮助程序来构建每个标签,将其添加到 StringBuilder,然后构建下一个标签,等等,然后使用 StringBuilder 实例创建 MvcHtmlString。非常丑陋,除非我可以做类似...

问题:

有没有办法:

停止 HtmlTextWriter 渲染到流,而是像 StringBuilder 一样使用它,在我用来创建 MvcHtmlString(或 HtmlString)的过程结束时?

听起来不太可能,即使我写...

附言:

HtmlTextWriter 的伟大之处在于您可以构建大量标签,而不是像使用 TagBuilder 那样一个接一个地构建它们。

最佳答案

与您收到的关于 other question 的回复相反Razor 不要求您返回 HtmlString。您的代码现在的问题是您直接 写入响应流。 Razor 执行由内而外的操作,这意味着您可能会弄乱响应顺序(参见 similar question)。

所以在你的情况下你可能会这样做(虽然我还没有测试过):

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

编辑(跟进以解决您的评论):

Html Helpers 完全有能力直接返回一个 HtmlString 或 void 并写入上下文编写器。例如,Html.PartialHtml.RenderPartial 在 Razor 中都可以正常工作。我认为您感到困惑的是调用一个版本而不是另一个版本所需的语法

例如,考虑一个 Aspx View :

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

您以不同的方式调用每个方法。如果你颠倒过来,事情就不会奏效。同样在 Razor 中:

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

与 Aspx 相比,Razor 中使用 void helper 的语法要冗长得多。但是,两者都可以正常工作。除非你的意思是“问题是 html 助手无法返回 void”。

顺便说一句,如果你真的想使用这种语法调用你的助手:@Html.Theseus() 你可以这样做:

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

但这有点像 hack。

关于asp.net-mvc - 为 Razor 调整自定义 Html Helper(它使用 HtmlTextWriter,因此返回 void),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4217611/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com