Nick Riggs, Web Developer

Making stuff up about web development since last week.

7 September 2010

Subscribe to our RSS feed

Posted in ASP.NET July 15, 2010

ASP.NET MVC typed html helpers generate helpful ready-to-bind markup for us. Learn how to detect what the resulting id and name attribute will be for use in your view code

The typed html helpers that were introduced in ASP.NET MVC 2 are great. If you not using them, you should be. Basically, you pass them an expression tree pointing at a property in your model and it renders the proper html – complete with a nested-delimited id and name attribute. For example, the follow:

<%= Html.TextBoxFor(m => m.Filters.Occurred.From) %>

Renders:

<input type="text" value="" name="Filters.Occurred.From" id="Filters_Occurred_From">

I recently ran into an issue where I needed to output the id that would be generated by using a typed helper. In the HtmlHelper class, I found a GenerateIdFromName method – but I still needed the generated name for that to work. After digging around in the MVC code for a while (open source is awesome), I found the magic and wrapped it all up into two simple yet helpful extension methods for my HtmlHelper:

public static class HtmlExtensions
{
    public static string NameFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        return htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName( ExpressionHelper.GetExpressionText(expression));
    }

    public static string IdFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    {
        return HtmlHelper.GenerateIdFromName(NameFor(htmlHelper, expression));
    }
}

So from our previous example, this view code:

<%= Html.NameFor(m => m.Filters.Occurred.From) %>
<%= Html.IdFor(m => m.Filters.Occurred.From) %>

Renders:

Filters.Occurred.From
Filters_Occurred_From

You might ask: why would you need to do that? In my case I was dynamically creating a lot of html that needed to be wired up to specific JavaScript objects.

Enjoy.