Reputation: 36592
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?
Upvotes: 33
Views: 30949
Reputation: 781
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:
namespace WebApp.Helpers
{
public static class Global
{
public static IHtmlString GetString()
{
return new HtmlString("Something <b>cool</b>");
}
}
}
<?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" />
@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()
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.
Upvotes: 3
Reputation: 4173
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));
Upvotes: 18
Reputation: 102428
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)
}
}
Upvotes: 16
Reputation: 887509
Razor helpers return HelperResult
objects.
You can get the raw HTML by calling ToString()
.
For more information, see my blog post.
Upvotes: 35