Converting ASP.NET MVC Razor @Helper Function into a Method of a Helper Class

Converting ASP.NET MVC Razor @helper function into a method of a helper class

The signature would need to be

public static MvcHtmlString FieldFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)

Then you use a combination of TagBuilder and the inbuilt html helper methods to generate the html

using System;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace YourAssembly.Html
{
public static class FieldHelper
{
public static MvcHtmlString FieldFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
MvcHtmlString label = LabelExtensions.LabelFor(helper, expression, new { @class = "control-label col-md-2" });
MvcHtmlString editor = EditorExtensions.EditorFor(helper, expression, new { htmlAttributes = new {@class = "form-control"}})
MvcHtmlString validation = ValidationExtensions.ValidationMessageFor(helper, expression, null, new { @class = "text-danger" });

StringBuilder html = new StringBuilder();
html.Append(editor);
html.Append(validation);
TagBuilder innerDiv = new TagBuilder("div");
innerDiv.AddCssClass("col-md-10");
innerDiv.InnerHtml = html.ToString();
html = new StringBuilder();
html.Append(label);
html.Append(innerDiv.ToString());
TagBuilder outerDiv = new TagBuilder("div");
outerDiv.AddCssClass("form-group");
outerDiv.InnerHtml = html.ToString();
return MvcHtmlString.Create(outerDiv.ToString());
}
}
}

Then your can make it available in all you views by adding it to web.config

<system.web.webPages.razor>
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
....
<add namespace="YourAssembly.Html" />
</namespaces>

Is it possible to pass a Razor construct to a helper method, using Razor's @: operator?

This is called an inline helper.

It's a Func<AnyType, HelperResult>.

You can call this delegate with a parameter, and the parameter will be accessible in the helper, named item.

Is it possible to create a generic @helper method with Razor?

No, this is not currently possible. You could write a normal HTML helper instead.

public static MvcHtmlString DoSomething<T, U>(
this HtmlHelper htmlHelper,
Expression<Func<T, U>> expr
) where T : class
{
...
}

and then:

@(Html.DoSomething<SomeModel, string>(x => x.SomeProperty))

or if you are targeting the model as first generic argument:

public static MvcHtmlString DoSomething<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expr
) where TModel : class
{
...
}

which will allow you to invoke it like this (assuming of course that your view is strongly typed, but that's a safe assumption because all views should be strongly typed anyways :-)):

@Html.DoSomething(x => x.SomeProperty)

Can I return a string using the @helper syntax in Razor?

Razor helpers return HelperResult objects.

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

For more information, see my blog post.

MVC Razor: Helper method to render alternate content when empty

You're looking for a helpers that will take a string and:

  1. If the string is not empty, render that string.
  2. If the string is not empty, render a given template.
  3. If the string is empty, render "N/A" html.
  4. If the string is empty, render a given template.

When passing a razor block to a function as a parameter, razor packages the block as Func. Change the parameters in the helper functions to take that type of delegate and don't forget to call those delegates (I chose to pass null).

These helpers should handle those scenarios.

Solution

@helper RenderThisOrThat(string stringToRender, Func<object, IHtmlString> leftTemplate = null, Func<object, IHtmlString> rightTemplate = null)
{
var shouldRenderLeft = !string.IsNullOrWhiteSpace(stringToRender);
leftTemplate = leftTemplate ?? (o => MvcHtmlString.Create(stringToRender));
@RenderThisOrThat(shouldRenderLeft, leftTemplate, rightTemplate)
}

@helper RenderThisOrThat(bool shouldRenderLeft, Func<object, IHtmlString> leftTemplate, Func<object, IHtmlString> rightTemplate = null)
{
var shouldRenderRight = !shouldRenderLeft;
if (shouldRenderRight)
{
if (rightTemplate != null)
{
@rightTemplate(null)
}
else
{
<span class='muted'>N/A</span>
}
}
else
{
@leftTemplate(null)
}
}

Examples

1. @Helpers.RenderThisOrThat(Model.StringWithBob)
2. @Helpers.RenderThisOrThat(Model.StringWithNull)
3. @Helpers.RenderThisOrThat(Model.StringWithBob, @<span>I'm @Model.StringWithBob</span>)
4. @Helpers.RenderThisOrThat(Model.StringWithNull, @<span>I'm @Model.StringWithBob</span>)
5. @Helpers.RenderThisOrThat(Model.StringWithBob, @<span>I'm @Model.StringWithBob</span>, @<span>What about Bob?</span>)
6. @Helpers.RenderThisOrThat(Model.StringWithNull, @<span>I'm @Model.StringWithBob</span>, @<span>What about Bob?</span>)

Will output:

  1. Bob
  2. <span class='muted'>N/A</span>
  3. <span>I'm Bob</span>
  4. <span class='muted'>N/A</span>
  5. <span>I'm Bob</span>
  6. <span>What about Bob?</span>

Razor helper method not working after upgrade from MVC 3 to 4

I found the work-around for this problem, but first a little history. For this particular MVC project, we decided to start implementing Razor gradually. The app has a lot of "modal" areas which are filled by making an AJAX call to get a partial view. These partial views were the first to get implemented as Razor views. Later, we wanted to implement a new feature in a standard ASPX view page using a Razor partial view, but the ASPX view engine cannot render a partial Razor view so instead of using a Razor view I added a MVC helper file in the App_Code folder with a method that renders the feature. This method is what is causing the error after upgrading to MVC4. The page with the feature rendered by this method is what I'm converting to a Razor view page so I realized today that all I need to do is move the code from that method into a Razor partial view. This fixed the problem, however, I still maintain that this is a bug in the Razor engine for rendering with helper methods.

mvc helper for rendering custom textbox

You can create a HtmlHelper extension method to output your html.

public static MvcHtmlString ToolTipTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> helper, 
Expression<Func<TModel, TValue>> expression, object htmlAttributes)
{
IDictionary<string, object> attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
attributes.Add("data-msg-number", "The field YearsInService must be a number.");
attributes.Add("data-rule-number", true);
... other 'fixed' attributes as required
return InputExtensions.TextBoxFor(helper, expression, attributes);
}

and then in the view

@ToolTipTextBoxFor(m => m.YearsInService, new { @class = "col-lg-1" })

and of course you could create other overloads to match the TextBoxFor() method overloads.

Edit

From your comments, you also want to generate data-rule- attributes based on the properties validation attributes. To do this, you can get the ModelMetatdata

ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);

and then check its properties

for example

if (metaData.IsRequired)
{
attributes.Add("data-rule-required", true);
}

@helper and Url.Action

you need to pass the UrlHelper to your method

@helper ShowPath(UrlHelper url)
{
<p class="migas">
<a href="@Url.Action("Index", "Home")">Home</a>
> <a href="@url.Action("Index", "AboutUs")">About Us</a>
> Directory</p>
}

and then from a view,

@YouAppCodeName.ShowPath(Url)

how can i display the value on a helper method inside my razor view

You do not need a code block (i.e. the @{}). Try using:

<td>
@item.companyname(item.AaaContactInfo.EMAILID)
</td>



Related Topics



Leave a reply



Submit