30

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)
1
  • Based on this answer, it is currently a limitation of putting custom Helpers in AppCode folder. Commented Jul 13, 2011 at 13:37

6 Answers 6

42
+50

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
Sign up to request clarification or add additional context in comments.

1 Comment

@Omid-RH I've declined the edit as I believe I explicitly put this namespace on HtmlHelper as there are conflicting classes with that name (From memory a generic and non-generic one) included by the prior using statements. If you can confirm this isn't the case you're welcome to propose the edit again and I will accept.
21

I used a workaround like following

@helper HtmlRaw(string s)
{
    @(new HtmlString(s))
}

@helper ReplaceCrLf(string strText)
{
    @HtmlRaw(HttpUtility
                        .HtmlEncode(strText)
                        .Replace(Environment.NewLine, "<br />"));
}

Comments

16

It is possible to get helpers from the PageContext:

var page = (WebViewPage) PageContext.Page;
var Url = page.Url;
var Html = page.Html;
var ViewBag = page.ViewBag;
// and so on

Usage (like standard helpers):

@Url.Action("Index", "Home")
@Html.Raw("some encoded string")

Comments

7

Looks like helpers in App_Code work but you don't have access to standard MVC Html. helpers

see Razor: Declarative HTML helpers

2 Comments

Darn it, that also eventually took me to the original blog where I saw how to do this in the first place. Here's looking forward to MVC4 then :(
Hi! I have created an idea in ASP.NET user voice related to this: Support @helper ExtensionMethod(this HtmlHelper html) for views in APP_CODE... help is appreciated in making it come to the front-lines... Thanks!
2

Add second Parameter in your helper as bellow

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

when you use this helper pass this.Html as second Parameter

Comments

2

This should be enough:

var message = new HtmlString(toast.Message.Replace(Environment.NewLine, "<br />"))

No need to use Html.Raw().

1 Comment

Confirmed, did it right in CSHTML <text>@(new HtmlString(ShortenedText))</text>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.