How to Display the Displayattribute.Description Attribute Value

How do I display the DisplayAttribute.Description attribute value?

I ended up with a helper like this:

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

public static class MvcHtmlHelpers
{
public static MvcHtmlString DescriptionFor<TModel, TValue>(this HtmlHelper<TModel> self, Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
var description = metadata.Description;

return MvcHtmlString.Create(string.Format(@"<span>{0}</span>", description));
}
}

Thanks to those who led me in the right direction. :)

How get the description attribute instead the name attribute for a model - (MVC asp.net)

You could get it from the metadata:

@model MyViewModel

@{
var description = ModelMetadata.FromLambdaExpression<MyViewModel, string>(x => x.field, ViewData).Description;
}

@description

Or if you are as me finding this absolutely horrible code to be written in a view you could encapsulate it in a reusable helper:

public static class HtmlExtensions
{
public static IHtmlString DescriptionFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression
)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
var description = metadata.Description;
return new HtmlString(description);
}
}

so that in your view you could use like that:

@model MyViewModel

@Html.DescriptionFor(x => x.field)

asp.net core Razor Pages: want DisplayAttribute Description to display as title/tooltip

You have to do it manually. As an example:

public static class Extensions
{
public static string GetDescription<T>(string propertyName) where T: class
{
MemberInfo memberInfo = typeof(T).GetProperty(propertyName);
if (memberInfo == null)
{
return null;
}

return memberInfo.GetCustomAttribute<DisplayAttribute>()?.GetDescription();
}
}

Usage:

<input asp-for="BorrowerName" class="form-control" title='@Extensions.GetDescription<YourClass>("BorrowerName")'/>

Extract Display name and description Attribute from within a HTML helper

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
...
}

Obtaining [Description]'s attribute value in CSHTML

You can simply write a custom HtmlHelper for that:

public static class HtmlHelpers
{
public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
if (expression == null)
throw new ArgumentNullException(nameof(expression));

DescriptionAttribute descriptionAttribute = null;
if (expression.Body is MemberExpression memberExpression)
{
descriptionAttribute = memberExpression.Member
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.Cast<DescriptionAttribute>()
.SingleOrDefault();
}

return new HtmlString(descriptionAttribute?.Description ?? string.Empty);
}
}

Is it possible to format Display attribute's Name property value of MVC Model class?

Add the <br/> attribute in displayattribute and display it as Html.Raw in the view. like this:

Model:

[DataType(DataType.Text)]
[Display(Name = "Corporation / <br/> Entreprise")]
public string Corporation { get; set; }

View:

<td class="col-md-6" style="font-weight:bold">
@Html.Raw(@Html.DisplayNameFor(model => model.Corporation))
</td>

Test Result:

Sample Image

ShortName in the Display attribute (DataAnnotations)

If you look at the Description for the ShortName property on the Display Attribute you'll see that it has a pretty limited scope out of the box:

Short Name Description

Of course, that doesn't limit you from leveraging that value on your Model Metadata, but there aren't any native helpers that do so.

Starting with MVC 2, ModelMetadata provides two methods to access the underlying data: FromStringExpression and FromLambdaExpression, so you don't really need to start from scratch in writing your own helper or extension method.

If you hate writing HTML helper methods, you can do this all inline:

@ModelMetadata.FromLambdaExpression<RegisterModel, string>( 
model => model.TransferDate, ViewData).ShortDisplayName} )

But it's also perfectly valid to add an extension method for consistency of access, deduplication of code, and improved error handling

public static class MvcHtmlHelpers
{
public static MvcHtmlString ShortNameFor<TModel, TValue>(this HtmlHelper<TModel> self,
Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
var name = metadata.ShortDisplayName ?? metadata.DisplayName ?? metadata.PropertyName;

return MvcHtmlString.Create(string.Format(@"<span>{0}</span>", name));
}
}

And then use like any other helper method:

@Html.ShortNameFor(model => model.TransferDate)

Further Reading:

  • How do I display the DisplayAttribute.Description attribute value?
  • MVC has long subsisted on custom extension methods, like needing DisplayNameFor before it was added in MVC 4
  • See this question for a quick breakdown of the differences between [Display(name="")] vs. [DisplayName("")] attributes
  • See this answer for working with ASP.NET MVC 6 / Core 1

ASP.NET Core: ShortName in the Display attribute (DataAnnotations)

To get the ShortName property using this method, you need to extract the Display attribute manually because it's not part of the default metadata. For example, something like this will work:

var defaultMetadata = m as 
Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata;
if(defaultMetadata != null)
{
var displayAttribute = defaultMetadata.Attributes.Attributes
.OfType<DisplayAttribute>()
.FirstOrDefault();
if(displayAttribute != null)
{
return displayAttribute.ShortName;
}
}
return m.DisplayName;

To plug that into your helpers, I would abstract away the method slightly as there's some duplicate code in there, so you would end up with a private method like this:

private static IHtmlContent MetaDataFor<TModel, TValue>(this IHtmlHelper<TModel> html, 
Expression<Func<TModel, TValue>> expression,
Func<ModelMetadata, string> property)
{
if (html == null) throw new ArgumentNullException(nameof(html));
if (expression == null) throw new ArgumentNullException(nameof(expression));

var modelExplorer = ExpressionMetadataProvider.FromLambdaExpression(expression, html.ViewData, html.MetadataProvider);
if (modelExplorer == null) throw new InvalidOperationException($"Failed to get model explorer for {ExpressionHelper.GetExpressionText(expression)}");
return new HtmlString(property(modelExplorer.Metadata));
}

And your two public methods like this:

public static IHtmlContent DescriptionFor<TModel, TValue>(this IHtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
return html.MetaDataFor(expression, m => m.Description);
}

public static IHtmlContent ShortNameFor<TModel, TValue>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression)
{
return html.MetaDataFor(expression, m =>
{
var defaultMetadata = m as
Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata;
if(defaultMetadata != null)
{
var displayAttribute = defaultMetadata.Attributes.Attributes
.OfType<DisplayAttribute>()
.FirstOrDefault();
if(displayAttribute != null)
{
return displayAttribute.ShortName;
}
}
//Return a default value if the property doesn't have a DisplayAttribute
return m.DisplayName;
});
}


Related Topics



Leave a reply



Submit