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

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


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

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.


Just replace

 @Html.Raw(extra)

with

@(new HtmlString(extra))

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;
    } 
} 

Comments

  1. Williams

    • 2019/12/18

    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 

  2. Andres

    • 2017/5/17

    Thanks Darin. Actually I was trying to convert from a helper method in code to a declarative helper. They are so very promising, but this limitation and the inability to use type arguments is a real shame. From the code in my answer I wonder whether a simple change to the Html property getter might provide this support.

  3. George

    • 2020/2/23

    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 

  4. Scott

    • 2019/10/4

    Razor is a markup syntax for embedding .NET based code into webpages. The Razor syntax consists of Razor markup, C#, and HTML. Files containing Razor generally have a .cshtml file extension. Razor is also found in Razor component files ( .razor ).

  5. Shiloh

    • 2019/1/11

    Performance of HtmlHelper vs Razor Helper (@helper) Display a string in place of a NULL date Html.BeginForm() in declarative helper methods.

  6. Martinez

    • 2017/4/13

    Html.Raw throw null reference exception when used in a customer HTML helper that renders an image [Answered] RSS 1 reply Last post Aug 12, 2016 04:30 PM by mohunt

  7. Travis

    • 2019/8/14

    The HTML helper instance that this method extends. The name of the child action method to invoke. Exceptions. ArgumentNullException. The htmlHelper parameter 

  8. Joaquin

    • 2015/8/26

    The @helper syntax within Razor enables you to easily create re-usable helper methods that can encapsulate output functionality within your view templates. They enable better code reuse, and can also facilitate more readable code. Let’s look at a super-simple scenario of how the @helper syntax can be used.

  9. Asher

    • 2016/8/15

    docs.microsoft.com › Docs › .NET › ASP.NET Core › Web apps › Blazor

  10. Martinelli

    • 2015/9/29

    Razor delegates as templates. Let's see how we can pass the Razor delegate as template to the html helper (that we saw in listing 2). The advantage of passing a template to the helper is we can display the server time in different styles.

  11. Johnson

    • 2015/10/22

    NET methods on the instance. Consider the following ReferenceChild component that logs a message when its ChildMethod is called. Shared/ 

  12. Fabbri

    • 2016/1/23

    You use HTML helpers in a view to render HTML content. An HTML helper, in most cases, is just a method that returns a string. You can build an entire ASP.NET MVC application without using a single HTML helper. However, HTML helpers make your life as a developer easier. By taking advantage of helpers, you can build your views with far less work.

  13. Alec

    • 2019/11/8

    Use data-source specific binding methods (for instance, BindToXML, BindToFolder) to bind an extensions to declarative data sources. Razor. @Html 

  14. Khalil

    • 2021/5/8

    मैं एक सरल कथात्मक एचटीएमएल सहायक लिखने के लिए कोशिश कर रहा हूँ: @helper Echo(string input) { @input } सहायक ठीक काम करता है अगर मैं इसे पेज मैं इस पर उपयोग करना चाहते हैं में

  15. Cameron

    • 2017/11/6

    Its built-in HTML helper methods produce standards-compliant NET MVC supports declarative validation rules defined with attributes from the. System.

Comments are closed.

Recent Posts