Question

I have a RazorHelpers.cshtml file in app_code which looks like:

@using Molecular.AdidasCoach.Library.GlobalConstants

@helper Translate(string key)
{
    @GlobalConfigs.GetTranslatedValue(key)
}

However, I have a case where I want to use the result as the link text in an @Html.ActionLink(...). I cannot cast the result to a string.

Is there any way to return plain strings from Razor helpers so that I can use them both in HTML and within an @Html helper?

Was it helpful?

Solution

Razor helpers return HelperResult objects.

You can get the raw HTML by calling ToString().

For more information, see my blog post.

OTHER TIPS

I don't think there is a way to make @helper return other types than HelperResult. But you could use a function with a return type of string, e.g.

@functions {
    public static string tr(string key) {
        return GlobalConfigs.GetTranslatedValue(key);
    }
}

then

@Html.ActionLink(tr("KEY"), "action", "controller")

See also http://www.mikesdotnetting.com/article/173/the-difference-between-helpers-and-functions-in-webmatrix

edit: MVC Razor: Helper result in html.actionlink suggests your helper can return a string by using @Html.Raw(GlobalConfigs.GetTranslatedValue(key));

In your case, I think this would also work:

@(GlobalConfigs.GetTranslatedValue(key))

Additional sample:

@helper GetTooltipContent()
{       
    if(Model.SubCategoryType == SUBCATTYPE.NUMBER_RANGE)
    {
        @(string.Format("{0} to {1}", Model.SubCategoryMinimum, Model.SubCategoryMaximum))
    }
    else if(Model.SubCategoryType == SUBCATTYPE.NUMBER_MAXIMUM)
    {
        @("<= " + Model.SubCategoryMaximum)
    }
    else if(Model.SubCategoryType == SUBCATTYPE.NUMBER_MINIMUM)
    {
        @(">= " + Model.SubCategoryMinimum)
    }
}

The following statements have been validated against MVC version 5.2.4.0. I am mostly targeting the part with: Is there any way to return plain strings from Razor helpers so that I can use them both in HTML and within an @Html helper?

I did some research on how the built in MVC helpers work and they are actually properties of System.Web.Mvc.WebViewPage class, so they have nothing to do with @helper feature.

Any @helper encodes strings as HTML and works as if the code is copy pasted to the View inside a Razor code block, aka @{ code }. On the other side, @functions are supposed to be used inside Razor blocks.

Well, if a @helper works as if the code is copy pasted, why not use @Html.Raw("<p>cool</p>")? Because the Html property is null inside helpers. Why? I have no idea.

Ok, but we can use a function to return a string and then apply @Html.Raw on the result. Does that work? Yes, it does. The following example creates a <p> element in the DOM:

@functions
{
    static string GetString()
    {
        return "<p>awesome</p>";
    }
}

@Html.Raw(GetString())

If you don't understand why @Html.Raw is necessary, please read this fine article from @SLaks about Razor automatic HTML encoding.

What about the approach with the built in properties? Yes, it is possible to create static classes with public methods that work just like that. The only problem is that you have to include the namespace in the View, with the @using keyword. Can that be improved? Yes, by adding the namespace in the Web.config within the Views folder. Example:

Helpers/Global.cs

namespace WebApp.Helpers
{
    public static class Global
    {
        public static IHtmlString GetString()
        {
            return new HtmlString("Something <b>cool</b>");
        }
    }
}

Views/Web.config

<?xml version="1.0"?>
<configuration>
  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <!-- Add to the end of namespaces tag. -->
        <add namespace="WebApp.Helpers" />

Usage

@Global.GetString()

What is the outcome? The text Something and an additional <b> element will be found in the DOM. If you need access to the Request, simply add an HttpContextBase parameter to the helper method and pass the WebViewPage.Context property when calling it.

Can it get better? Yes, as always. The same output can be created with @helper and @functions:

@helper GetString1()
{
    @(new HtmlString("Something <b>awesome</b>"))
}

@functions {
    public static IHtmlString GetString2()
    {
        return new HtmlString("Something <b>awesome</b>");
    }
}

@MyHelper.GetString1()
@MyHelper.GetString2()

Answer

Regarding OP's question, I recommend @Spikolynn's approach to create a function that returns string. However, if you need to write many lines of C# code in the helper, I suggest using a static class helper.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top