8

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?

Chris
  • 6,914
  • 5
  • 54
  • 80
Banshee
  • 15,376
  • 38
  • 128
  • 219

1 Answers1

20

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
    ...
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks! But this is not working, the DisplayName and Description is null? Pleas note that this is in MVC2 and not MVC3. If I got it right your solution will only work in MVC3? – Banshee Feb 11 '11 at 21:04
  • @SnowJim, yes, 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. In .NET 4.0 it should work. – Darin Dimitrov Feb 11 '11 at 21:34
  • 1
    @SnowJim, please see my UPDATE for a workaround in ASP.NET MVC 2. – Darin Dimitrov Feb 11 '11 at 21:46
  • This is one of the most comprehensive answers I have come accross, so +1. Thank you @DarinDimitrov! – RvdV79 Aug 14 '13 at 13:09