Search code examples
asp.net-mvcasp.net-mvc-3razorrazor-declarative-helpers

Using @Html inside shared @helper in App_Code


I am building a very basic MVC3 site while I learn and I am having difficulty with the following declarative Razor html helper.

Inside RMB.cshtml inside App_Code folder:

@helper ReplaceCrLf(string strText)
{
    @Html.Raw(Html.Encode(strText).Replace(Environment.NewLine, "<br />"));
}

Inside my index.cshtml view:

@RMB.ReplaceCrLf(Model.Post)

This gives me a null reference exception on Html in the helper, because it doesn't seem to know what it is. I can work around this by passing Html from the view to the helper, but I was wondering if there is another way for my shared html helpers to be able to reference Html without me having to pass it in to ever helper I write?

For completeness, here is the working workaround:

In RMB.cshtml in App_Code

@helper ReplaceCrLf(string strText, System.Web.Mvc.HtmlHelper Html)
{
    @Html.Raw(Html.Encode(strText).Replace(Environment.NewLine, "<br />"));
}

In index.cshtml view

@RMB.ReplaceCrLf(Model.Post, Html)

Solution

  • I add this to any .cshtml files in App_Code now.

    // Using's are needed to ensure helpers function correctly.
    @using System.Web.Mvc;
    @using System.Web.Mvc.Html;
    @using System.Web.Mvc.Routing;
    @using System.Web.Mvc.Razor;
    @functions {
        private static WebViewPage page { get { return PageContext.Page as WebViewPage; } } 
        private static System.Web.Mvc.HtmlHelper<dynamic> html { get { return page.Html; } }
        private static UrlHelper url { get { return page.Url; } }
        private static dynamic viewBag { get { return page.ViewBag; } }
    }
    

    EDIT: Have modified the helper variable names to lowercase as I have had some conflicts with the built-in helpers names. I have modified the HTML helper to be generic which allows the use of TextBoxFor etc helpers

    This makes those wonderful helpers available to all @helper methods and functions in the file.

    Many thanks to Neshta for the original concept!


    Complete Example to answer the question:

    In RMB.cshtml in the App_Code folder

    @functions {
        public static WebViewPage page = (PageContext.Page as WebViewPage);
        public static HtmlHelper<object> html = page.Html;
    }
    
    @helper ReplaceCrLf(string strText)
    {
        @html.Raw(html.Encode(strText).Replace(Environment.NewLine, "<br />"));
    }
    

    In View:

    @RMB.ReplaceCrLf("line1\nline2") // No passing HtmlHelper