Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the HtmlHelper instance null in a Razor declarative @helper method?

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.

like image 515
Drew Noakes Avatar asked Mar 12 '11 13:03

Drew Noakes


3 Answers

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

like image 117
kkara Avatar answered Oct 15 '22 22:10

kkara


That's a known limitation of those helpers. One possibility is to pass it as parameter:

@helper TestHelperMethod(HtmlHelper html) {
    var extra = "class=\"foo\"";
    <[email protected](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()
like image 35
Darin Dimitrov Avatar answered Oct 15 '22 20:10

Darin Dimitrov


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.

like image 26
BritishDeveloper Avatar answered Oct 15 '22 22:10

BritishDeveloper