ASP.NET MVC: пользовательские помощники Html в бритве

У меня возникают трудности с помощниками Html при использовании с Razor. Указанные помощники отлично работали в MVC 2 с движком просмотра веб-форм. Но не в бритве. Ошибка во время выполнения:

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)

Расширение Show Show Compiler Output показывает:

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).

Я не получаю ошибок во время компиляции, хотя строка кода (@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 - это просто перечисление, которое определяет способ отображения меню. Не зацикливайтесь на этом, так как это нормально.

Ответ 1

Вы можете вызвать своего помощника следующим образом:

@{ Html.IncrementalMenu(MenuBlock.Site); }

Синтаксис WebForms

<% Html.IncrementalMenu(MenuBlock.Site); %>

Вы просто вызываете свой метод, и возвращаемое значение (если оно есть) игнорируется.

Код, подобный этому, ожидает возвращаемое значение и записывает возвращаемое значение в поток html:

@Html.YourHelper()

Синтаксис Webforms:

<%: Html.YourHelper() %>

То же самое, если значение результата!= IHtmlString:

<%= Server.HtmlEncode(Html.YourHelper()) %>

Ответ 2

Добавление:

Вы можете получить такую ​​же или подобную ошибку с помощью @Html.RenderPartial. В этом случае это связано с тем, что RenderPartial отображает непосредственно ответ, поэтому не является строкой и должен быть закодирован внутри "блока кода Razor":

@{
   Html.RenderPartial(...);
}

Я подозреваю, что это одна из причин, по которой Microsoft включила в ASP.NET MVC новый Html.Partial. Поскольку Html.Partial возвращает строку, это нормально:

@Html.Partial

Что выглядит намного лучше. Учитывая, что одна из заявленных целей Razor должна быть легкой на первый взгляд, это вполне вероятно.

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

И это соответствует старой поговорке, что, наконец, Microsoft получит свои продукты в версии 3. EG, Access 97.

Это удручающее сравнение. Потому что они ввернули вещи в версии 4, то есть Access 2000...

Ответ 3

Ваш помощник HTML должен возвращать MvcHtmlString, который представляет html для правильной работы с Razor (и другими механизмами просмотра, которые не являются WebFormsViewEngine)

public static MvcHtmlString Label(this HtmlHelper html, string expression)
{
    return MvcHtmlString.Create("<label>" + expression + "</label>");
}