Strongly Typed <label> elements in ASP.NET MVC 2

19 January 2010 - 11:23 PM / by Dominic Pettifer. 2 Comments

Cool C# Snippets - Generate strongly typed <label> elements in a way that is (IMHO) better than the default method built into ASP.NET MVC 2.

Strongly Typed Html Helpers

In ASP.NET MVC version 2.0 they introduced support for strongly typed <input /> controls. Whereas before you'd have to type something along the lines of:

<%= Html.TextBox("EmailAddress", Model.EmailAddress) %>

The problem being that you could mistype "EmailAddress" and the error wouldn't get picked up until runtime, or you might rename the property "EmailAddress" on your ViewModel, and refactoring tools built into Visual Studio wouldn't pick up the "EmailAddress" string used in the TextBox() method. Now in ASP.NET MVC 2 there is support for strongly typed HTML Helper methods, where any errors can be picked up at compile time:

<%= Html.TextBoxFor(m => m.EmailAddress) %>

Read more at Scott Guthrie's blog (http://weblogs.asp.net/scottgu/archive/2010/01/10/asp-net-mvc-2-strongly-typed-html-helpers.aspx).

Html.LabelFor()

In MVC 2 they also added support for strongly typed <label> elements as well (sort of):

<%= Html.LabelFor(m => m.EmailAddress) %>

...which outputs the following...

<label for="EmailAddress">EmailAddress</label>

The benefits of this method being that it will reliably generate the 'for' attribute that points to the <input /> element's ID its paired with, eg.

<label for=”EmailAddress”>EmailAddress</label>
<input type=”text” id=”EmailAddress” name=”EmailAddress” />

However, Html.LabelFor has no overload that allows you to specify the actual <label> element text, it defaults to the property name (EmailAddress) which looks ugly. You can set the label text via DataAnnotations on the ViewModel class itself eg.

public class AccountView
{
    //-- snip (other properties) --//
    
    [Required]
    [DisplayName(“Your e-mail address:”)]
    public string EmailAddress { get; set; }
}

...and you'll get:

<label for="EmailAddress">Your e-mail address:</label>

Not In My ViewModel Please!

The problem is some people, like me, would consider the <label> text to be a View/Presentation concern specified in the .aspx views, and that it shouldn’t go inside your Model classes. You could just type <label for="EmailAddress"> directly, but then you lose the benefit of strong typing the Input's ID. So I wrote an Html Extension method that generates the control Ids based on the ViewModel Property:

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

namespace MvcLibrary.Extensions
{
    public static class HtmlExtensions
    {
        public static MvcHtmlString FieldIdFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
        {
            string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
            string inputFieldId = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName);
            return MvcHtmlString.Create(inputFieldId);
        }
    }
}

Which you can use in your Views like this:

<label for="<%= Html.FieldIdFor(m => m.EmailAddress) %>">Your e-mail address:</label>
<%= Html.TextBoxFor(m => m.EmailAddress) %>

I suppose one could just write an overload for the LabelFor() method that takes a string parameter for the label text. However, just generating the input ID has other benefits. For one you’re more in control of the markup if you want to add attributes (class, id etc.) to the <label> element. Secondly the Html.FieldIdFor() method can be used elsewhere you need the dynamically generated control ID, such as in calling JavaScript functions that make the ID of input controls.

<script> $.CoolJQueryFunction('<%= Html.FieldIdFor(m => m.EmailAddress) %>'); </script>

2 Comments on "<label> Elements in ASP.NET MVC"

Post a Comment
  • RE: <label> Elements in ASP.NET MVC

    Thank you.

    I'm using your helper when I want to show validation message inside label:

    <label for="<%= Html.FieldIdFor(x => x.Article.Title) %>">Title: <%= Html.ValidationMessageFor(x => x.Article.Title, "*") %></label>

    Posted on 10 July 2010 - 2:53 AM / by Denis

  • RE: <label> Elements in ASP.NET MVC

    For once I'm going to disagree with you.
    IMO, your View Model (not Domain Model) are a direct View/Presentation concern. (Actually I see it as a new generation of "code behind")

    What you do in your ViewModel are what you want expressed in your view, while this View Model get mapped (with an OOM or manually) to a Domain Model where there should be no presentation logic at all.

    Just my 20 cents, but typing <label for="<%= Html.FieldIdFor(m => m.EmailAddress) %>">Your e-mail address:</label> seems like an aweful lot of work if you have 1000 labels all over your application.

    1 View = 1 View Model = Any Number of/part of Domain Models. No?

    Posted on 14 May 2010 - 6:09 AM / by Krokonoster

Leave a Comment

In Reply to comment by "Krokonoster"

For once I'm going to disagree with you.
IMO, your View Model (not Domain Model) are a direct View/Presentation concern. (Actually I see it as a new generation of "code behind")

What you do in your ViewModel are what you want expressed in your view, while this View Model get mapped (with an OOM or manually) to a Domain Model where there should be no presentation logic at all.

Just my 20 cents, but typing <label for="<%= Html.FieldIdFor(m => m.EmailAddress) %>">Your e-mail address:</label> seems like an aweful lot of work if you have 1000 labels all over your application.

1 View = 1 View Model = Any Number of/part of Domain Models. No?

Comment Details
*
* BBCode: [b]bold[/b], [i]italics[/i], [code]code[/code], [li]bullet point[/li], [h]Heading[/h], [url="http://www.example.com"]link[/url], [quote author="John Smith"]quote[/quote]

Random Image

HttpApplication context pooling with multiple requests

HttpApplication context pooling with multiple requests (from the blog IHttpModule Gotchas – The Init() Method Can Get Called Multiple Times )

Quick Poll

What is your DIP/IOC Container of choice?

Poll Vote
(see results)
View Comments (4) (See previous polls)

Latest Tweets

View Dominic Pettifer's Twitter page.