Using MVC 3 RTM I'm getting a strange NullReferenceException
:
@helper TestHelperMethod() {
var extra = "class=\"foo\"";
<div @Html.Raw(extra)></div>
}
It turns out that Html
(of type HtmlHelper
) is null
.
I've never seen this before in a regular view. I'm starting to experiment with declarative helper methods in Razor (so far they seem a little limited) and I'm quite stumped by what I'm seeing here.
That's a known limitation of those helpers. One possibility is to pass it as parameter:
@helper TestHelperMethod(HtmlHelper html) {
var extra = "class=\"foo\"";
<div@html.Raw(extra)></div>
}
Another possibility is to write the helper as an extension method:
public static class HtmlExtensions
{
public static MvcHtmlString TestHelperMethod(this HtmlHelper)
{
var div = new TagBuilder("div");
div.AddCssClass("foo");
return MvcHtmlString.Create(div.ToString());
}
}
and then:
@Html.TestHelperMethod()
Using Drew Noakes suggestion, I have come to a workaround that does the trick for now and that can be easily removed once the issue is solved in a newer version of MVC (that is if more stuff isn't changed that would break it:))
The goal is to be able to use an HtmlHelper inside a declarative helper method that lives in a file in App_Code without having a NullReferenceException. To solve this I included in all the files in App_Code the following:
@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; }
}
}
This does seem to do the trick as I can now write the following helper (in the same file):
@helper PrintAsRaw(string htmlString)
{
@Html.Raw(htmlString)
}
Obviously the helper method is just an example. This solution has the downside that the @functions declarations has to be introduced in all helper declaration files in App_Code, but does avoid complicating the call to the helper, as you can simply write in a view:
@MyAppCodeFile.PrintAsRaw("<p>My paragraph</p>")
Hope this helps...
I know it's not the point but if it is just Html.Raw(value)
you were hoping to use when finding this question on Google (as I was) according to the source code of System.Web.Mvc.dll all Html.Raw does is:
public IHtmlString Raw(string calue)
{
return new HtmlString(value);
}
So I've just used @(new HtmlString(value))
in my helper which works nicely.
I think I know what's causing the issue...
The definition of the Html
property getter is:
public static HtmlHelper Html {
get {
WebPage currentWebPage = CurrentPage as WebPage;
if (currentWebPage == null) {
return null;
}
return currentWebPage.Html;
}
}
Setting a breakpoint in my helper method shows that CurrentPage
is not in fact an instance of WebPage
, hence the null
value.
Here is the type hierarchy of CurrentPage
(my class names doctored slightly):
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
Note that the base class of my view has been specified in Web.config:
<system.web.webPages.razor>
<pages pageBaseType="My.Site.MyWebViewPage">
...
Which is defined both in generic and non-generic form:
public abstract class MyWebViewPage : WebViewPage { ... }
public abstract class MyWebViewPage<TModel> : WebViewPage<TModel> { ... }
So, if this problem does not occur for others, perhaps they're not using a custom pageBaseType
.
Note too that I've placed the @helper
declaration in App_Code\Helpers.cshtml
in the hope of making it globally accessible.
Am I doing something wrong, or is this a bug?
EDIT Thanks Darin for pointing out this as a known issue. Still, why isn't the Html
property redefined as:
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;
}
}
I had the same issue and this line of code did the trick. It´s not a solution for using HtmlHelper, it's just a way of writing RAW html in a declarative razor helper.
@{CurrentPage.WriteLiteral("html code");}