Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract Display name and description Attribute from within a HTML helper

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?

like image 740
Banshee Avatar asked Feb 11 '11 20:02

Banshee


1 Answers

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
    ...
}
like image 95
Darin Dimitrov Avatar answered Oct 03 '22 22:10

Darin Dimitrov