Extract Display name and description Attribute from within a HTML helper

asp.net-mvc-2, attributes, c#, html-helper, reflection

Solution

Disclaimer: The following works only with ASP.NET MVC 3 (see the update at the bottom if you are using previous versions)

Assuming the following model:

public class MyViewModel
{
    [Display(Description = "some description", Name = "some name")]
    public string SomeProperty { get; set; }
}

And the following view:

<%= Html.LabelFor(x => x.SomeProperty, true) %>

Inside your custom helper you could fetch this information from the metadata:

public static MvcHtmlString LabelFor<TModel, TValue>(
    this HtmlHelper<TModel> self, 
    Expression<Func<TModel, TValue>> expression, 
    bool showToolTip
)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
    var description = metadata.Description; // will equal "some description"
    var name = metadata.DisplayName; // will equal "some name"
    // TODO: do something with the name and the description
    ...
}

Remark: Having `[DisplayName("foo")]` and `[Display(Name = "bar")]` on the same model property is redundant and the name used in the `[Display]` attribute has precedence in `metadata.DisplayName`.

UPDATE:

My previous answer won't work with ASP.NET MVC 2.0. There are a couples of properties that it is not possible to fill by default with `DataAnnotations` in .NET 3.5, and `Description` is one of them. To achieve this in ASP.NET MVC 2.0 you could use a custom model metadata provider:

public class DisplayMetaDataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes, 
        Type containerType,
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName
    )
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

        var displayAttribute = attributes.OfType<DisplayAttribute>().FirstOrDefault();
        if (displayAttribute != null)
        {
            metadata.Description = displayAttribute.Description;
            metadata.DisplayName = displayAttribute.Name;
        }
        return metadata;
    }
}

which you would register in `Application_Start`:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    ModelMetadataProviders.Current = new DisplayMetaDataProvider();
}

and then the helper should work as expected:

public static MvcHtmlString LabelFor<TModel, TValue>(
    this HtmlHelper<TModel> self, 
    Expression<Func<TModel, TValue>> expression, 
    bool showToolTip
)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
    var description = metadata.Description; // will equal "some description"
    var name = metadata.DisplayName; // will equal "some name"
    // TODO: do something with the name and the description
    ...
}

Problem

I am building a custom `HTML.LabelFor` helper that looks like this : ``` public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression, Boolean showToolTip) { var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData); ... } ``` To be able to get the proper name for the property I am using the following code : ``` metadata.DisplayName ``` And on the property of the ModelView class I got : ``` [DisplayName("Titel")] ``` The problem is that I also need a description. There is an Attribute called Display and that has Name and Description but I do not see how to extract this with the metadata variable in the above code?

Original source