Почему экземпляр HtmlHelper null в декларативном методе @helper Razor?
Использование RTM MVC 3 Я получаю странный NullReferenceException
:
@helper TestHelperMethod() {
var extra = "class=\"foo\"";
<div @Html.Raw(extra)></div>
}
Оказывается, что Html
(типа HtmlHelper
) null
.
Я никогда не видел этого раньше в обычном режиме. Я начинаю экспериментировать с декларативными вспомогательными методами в Razor (пока они кажутся немного ограниченными), и я совершенно озадачен тем, что вижу здесь.
Ответы
Ответ 1
Это известное ограничение этих помощников. Одна из возможностей - передать его в качестве параметра:
@helper TestHelperMethod(HtmlHelper html) {
var extra = "class=\"foo\"";
<[email protected](extra)></div>
}
Другая возможность заключается в том, чтобы написать помощник как метод расширения:
public static class HtmlExtensions
{
public static MvcHtmlString TestHelperMethod(this HtmlHelper)
{
var div = new TagBuilder("div");
div.AddCssClass("foo");
return MvcHtmlString.Create(div.ToString());
}
}
а затем:
@Html.TestHelperMethod()
Ответ 2
Используя предложение Drew Noakes, я пришел к обходу, который сейчас делает трюк, и который можно легко удалить, как только проблема будет решена в более новой версии MVC (то есть, если больше вещей не изменилось, что бы сломать его:))
Цель состоит в том, чтобы использовать HtmlHelper внутри декларативного вспомогательного метода, который живет в файле в App_Code без исключения NullReferenceException. Чтобы решить эту проблему, я включил во все файлы в App_Code следующее:
@using System.Web.Mvc;
@functions
{
private static new HtmlHelper<object> Html
{
get { return ((WebViewPage)CurrentPage).Html; }
}
private static UrlHelper Url
{
get { return ((WebViewPage)CurrentPage).Url; }
}
}
Это похоже на трюк, поскольку теперь я могу написать следующий помощник (в том же файле):
@helper PrintAsRaw(string htmlString)
{
@Html.Raw(htmlString)
}
Очевидно, что вспомогательный метод является лишь примером. Это решение имеет недостаток, что объявления @functions должны быть введены во всех файлах декларации помощника в App_Code, но не позволяют усложнять вызов помощнику, поскольку вы можете просто написать в виде:
@MyAppCodeFile.PrintAsRaw("<p>My paragraph</p>")
Надеюсь, что это поможет...
Ответ 3
Я знаю, что это не так, но если это просто Html.Raw(value)
, вы надеялись использовать, когда находите этот вопрос в Google (как я был) в соответствии с исходным кодом System.Web.Mvc.dll все Html.Raw do:
public IHtmlString Raw(string calue)
{
return new HtmlString(value);
}
Итак, я только что использовал @(new HtmlString(value))
в моем помощнике, который прекрасно работает.
Ответ 4
Просто замените
@Html.Raw(extra)
с
@(new HtmlString(extra))
Ответ 5
Я думаю, что знаю, что вызывает проблему...
Определение атрибута свойства Html
:
public static HtmlHelper Html {
get {
WebPage currentWebPage = CurrentPage as WebPage;
if (currentWebPage == null) {
return null;
}
return currentWebPage.Html;
}
}
Установка точки останова в моем вспомогательном методе показывает, что CurrentPage
на самом деле не является экземпляром WebPage
, поэтому значение null
.
Ниже приведена иерархия типов CurrentPage
(мои имена классов немного модифицированы):
ASP._Page_Views_mycontroller_View_cshtml
My.Site.MyWebViewPage`1
System.Web.Mvc.WebViewPage`1
System.Web.Mvc.WebViewPage
System.Web.WebPages.WebPageBase
System.Web.WebPages.WebPageRenderingBase
System.Web.WebPages.WebPageExecutingBase
System.Object
Обратите внимание, что базовый класс моего представления указан в Web.config:
<system.web.webPages.razor>
<pages pageBaseType="My.Site.MyWebViewPage">
...
который определяется как в общей, так и в не общей форме:
public abstract class MyWebViewPage : WebViewPage { ... }
public abstract class MyWebViewPage<TModel> : WebViewPage<TModel> { ... }
Итак, если эта проблема не возникает для других, возможно, они не используют пользовательский pageBaseType
.
Заметьте, что я разместил объявление @helper
в App_Code\Helpers.cshtml
в надежде сделать его доступным по всему миру.
Я делаю что-то неправильно или это ошибка?
EDIT Спасибо Дарин за то, что он указал на это как на известную проблему. Тем не менее, почему свойство Html
не переопределяется как:
public static HtmlHelper Html {
get {
WebPage currentWebPage = CurrentPage as WebPage;
if (currentWebPage != null) {
return currentWebPage.Html;
}
WebViewPage currentWebViewPage = CurrentPage as WebViewPage;
if (currentWebViewPage != null) {
return currentWebViewPage.Html;
}
return null;
}
}
Ответ 6
У меня была такая же проблема, и эта строка кода сделала трюк. Это не решение для использования HtmlHelper, это просто способ записи RAW html в декларативном помощнике бритвы.
@{CurrentPage.WriteLiteral("html code");}