与Razor一起使用时,我遇到了Html Helpers的困难。所述助手在MVC 2中与web表单视图引擎一起工作良好。但不是剃须刀。我在运行时得到的错误是:
Compiler Error Message: CS1502: The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments
Source Error:
Line 1: @using Wingspan.Web.Mvc;
Line 2: @Html.IncrementalMenu(MenuBlock.Site)
展开显示详细的编译器输出显示:
d:\...\Views\Shared\MenuTop.cshtml(2,1): error CS1502: The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments
d:\...\Views\Shared\MenuTop.cshtml(2,7): error CS1503: Argument 1: cannot convert from 'void' to 'System.Web.WebPages.HelperResult'
这向我表明剃刀不喜欢我的助手,IncrementalMenu,返回void(在MVC 2 web表单引擎视图中工作正常)。
我在编译时没有出现任何错误,尽管代码行(@ Html.IncrementalMenu(...))带有下划线的红色下划线:
Cannot implicitly convert type 'void' to 'object'
IncrementalMenu位于Wingspan.Web.Mvc名称空间中。它的签名如下:
public static void IncrementalMenu(this HtmlHelper html, MenuBlock menuBlock)
{
// Uses an HtmlTextWriter to render a menu from the sitemap
}
如果我知道出了什么问题,我会被打击......
PS:
MenuBlock参数只是一个枚举,用于标识菜单应如何呈现。不要因为这很好而注意这一点。
答案 0 :(得分:85)
你可以这样打电话给你的帮手:
@{ Html.IncrementalMenu(MenuBlock.Site); }
WebForms语法
<% Html.IncrementalMenu(MenuBlock.Site); %>
您只需调用您的方法,并忽略返回值(如果有)。
这样的代码需要返回值,并将返回值写入html流:
@Html.YourHelper()
Webforms语法:
<%: Html.YourHelper() %>
同样,如果结果值!= IHtmlString:
<%= Server.HtmlEncode(Html.YourHelper()) %>
答案 1 :(得分:49)
您可以使用@ Html.RenderPartial获得相同或类似的错误。在这种情况下,由于RenderPartial直接呈现给Response,因此不是字符串,需要在“Razor代码块”内编码:
@{
Html.RenderPartial(...);
}
我怀疑这是微软在ASP.NET MVC中包含新Html.Partial的原因之一。由于Html.Partial确实返回一个字符串,所以可以写:
@Html.Partial
看起来好多了。鉴于Razor声明的目标之一是易于实现的,这很可能是正确的。
这也让我感觉更舒服。我知道返回一个字符串是什么,我一直这样做。但是“回到响应”每次我想都会需要更多的脑循环。
它符合最初微软在版本3中获得产品的古老格言.EG,Access 97.
这是令人沮丧的明喻。他们在版本4中搞砸了,即Access 2000 ......
答案 2 :(得分:22)
你的HTML助手应该返回代表html的MvcHtmlString,以便与Razor(以及其他不属于WebFormsViewEngine的视图引擎)一起正常工作
public static MvcHtmlString Label(this HtmlHelper html, string expression)
{
return MvcHtmlString.Create("<label>" + expression + "</label>");
}