100
public class Class1
{
    [DisplayName("Something To Name")]
    public virtual string Name { get; set; }
}

How to get the value of DisplayName attribute in C# ?

be_good_do_good
  • 4,311
  • 3
  • 28
  • 42
Bassam Bsata
  • 1,075
  • 2
  • 10
  • 13

18 Answers18

106

Try these utility methods of mine:

using System.ComponentModel;
using System.Globalization;
using System.Linq;


public static T GetAttribute<T>(this MemberInfo member, bool isRequired)
    where T : Attribute
{
    var attribute = member.GetCustomAttributes(typeof(T), false).SingleOrDefault();

    if (attribute == null && isRequired)
    {
        throw new ArgumentException(
            string.Format(
                CultureInfo.InvariantCulture, 
                "The {0} attribute must be defined on member {1}", 
                typeof(T).Name, 
                member.Name));
    }

    return (T)attribute;
}

public static string GetPropertyDisplayName<T>(Expression<Func<T, object>> propertyExpression)
{
    var memberInfo = GetPropertyInformation(propertyExpression.Body);
    if (memberInfo == null)
    {
        throw new ArgumentException(
            "No property reference expression was found.",
            "propertyExpression");
    }

    var attr = memberInfo.GetAttribute<DisplayNameAttribute>(false);
    if (attr == null)
    {
        return memberInfo.Name;
    }

    return attr.DisplayName;
}

public static MemberInfo GetPropertyInformation(Expression propertyExpression)
{
    Debug.Assert(propertyExpression != null, "propertyExpression != null");
    MemberExpression memberExpr = propertyExpression as MemberExpression;
    if (memberExpr == null)
    {
        UnaryExpression unaryExpr = propertyExpression as UnaryExpression;
        if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
        {
            memberExpr = unaryExpr.Operand as MemberExpression;
        }
    }

    if (memberExpr != null && memberExpr.Member.MemberType == MemberTypes.Property)
    {
        return memberExpr.Member;
    }

    return null;
}

Usage would be:

string displayName = ReflectionExtensions.GetPropertyDisplayName<SomeClass>(i => i.SomeProperty);
Rich Tebb
  • 6,806
  • 2
  • 23
  • 25
  • Could u help me to find out proper way to iterate through all properties DisplayName, please? http://stackoverflow.com/questions/12868901/how-to-iterate-through-the-all-model-properties-mvc-4 – NoWar Oct 13 '12 at 00:53
  • 2
    @rich-tebb It seems this doesn't work when you have [Display(Name = "SomeProperty", ResourceType = typeof(SomeResource))], it doesn't return localized name. Will try to modify it so it does. – Matija Grcic Dec 04 '13 at 15:25
  • Added a little code snippet how to read the localized value from DisplayAttribute. – Matija Grcic Dec 04 '13 at 18:46
  • 1
    public static T GetAttribute(this extension method cannot be declared in a non-generic, non-nested static class – MIKE May 17 '16 at 17:03
  • public static ThankYou – Ashraf Sada Nov 11 '20 at 16:44
42

First off, you need to get a MemberInfo object that represents that property. You will need to do some form of reflection:

MemberInfo property = typeof(Class1).GetProperty("Name");

(I'm using "old-style" reflection, but you can also use an expression tree if you have access to the type at compile-time)

Then you can fetch the attribute and obtain the value of the DisplayName property:

var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
      .Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;

() parentheses are required typo error

Community
  • 1
  • 1
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • 5
    If the displayNameAttribute is null, this will fail. Instead of returning single try to return FirstOrDefault() then check whether this value is null or not. – rkmorgan Jan 09 '16 at 00:05
34

You need to get the PropertyInfo associated with the property (e.g. via typeof(Class1).GetProperty("Name")) and then call GetCustomAttributes.

It's a bit messy due to returning multiple values - you may well want to write a helper method to do this if you need it from a few places. (There may already be a helper method in the framework somewhere, but if there is I'm unaware of it.)

EDIT: As leppie pointed out, there is such a method: Attribute.GetCustomAttribute(MemberInfo, Type)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 20
    We got `Attribute.GetCustomAttribute(MemberInfo, Type)` :) http://msdn.microsoft.com/en-us/library/ms130863 – leppie Feb 16 '11 at 12:27
  • 1
    @leppie: Ooh, nice. Not sure why I'd never spotted that. – Jon Skeet Feb 16 '11 at 13:15
  • 2
    @cesAR: You've posted a link back to *this* question. But please don't do this in general - leaving comments on one answer linking to another question is almost never appropriate. – Jon Skeet Aug 10 '20 at 05:51
14

If anyone is interested in getting the localized string from the property with DisplayAttribute and ResourceType like this:

[Display(Name = "Year", ResourceType = typeof(ArrivalsResource))]
public int Year { get; set; }

Use the following after displayAttribute != null (as shown above by @alex' answer):

ResourceManager resourceManager = new ResourceManager(displayAttribute.ResourceType);
var entry = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true)
                           .OfType<DictionaryEntry>()
                           .FirstOrDefault(p => p.Key.ToString() == displayAttribute.Name);

return entry.Value.ToString();
Community
  • 1
  • 1
Matija Grcic
  • 12,963
  • 6
  • 62
  • 90
  • 7
    `DisplayAttribute` has `GetName` method. No need for your code in .NET 4+ : https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.getname%28v=vs.110%29.aspx – Salar Nov 18 '15 at 06:30
  • 1
    @Salar While you are correct you're slightly misled - when a ResourceType is specified, then the `GetName()` method just returns the Key, and not the Value specified in the resources file. – Matt Griffiths May 24 '16 at 15:32
  • @MattGriffiths what is this variable '**displayAttribute**' ? – Dark_Knight Jul 25 '16 at 09:44
  • @Dark_Knight that's probably the variable holding the result of that display attribute query, see http://stackoverflow.com/a/10048758/3941350 for an example on how to do that. – Yoda Oct 26 '16 at 10:41
  • as pointed out by Salar, it's better to use `.GetName()` instead of the code above, see the problem I had with the code above here : http://stackoverflow.com/questions/43827360/with-entityframework-how-to-access-displayname-for-foreign-key-columns – JP Tétreault May 07 '17 at 06:13
  • Hi Matija , I'm looking for some help here in my question, I think maybe you could have some knowledge related. Thanks! https://stackoverflow.com/questions/5015830/get-the-value-of-displayname-attribute – cesAR Aug 09 '20 at 21:48
13
var propInfo = typeof(Class1).GetProperty("Name");
var displayNameAttribute = propInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);
var displayName = (displayNameAttribute[0] as DisplayNameAttribute).DisplayName;

displayName variable now holds the property's value.

Donal
  • 31,121
  • 10
  • 63
  • 72
12

From within a view that has Class1 as it's strongly typed view model:

ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
Luke Bennett
  • 32,786
  • 3
  • 30
  • 57
  • I think this should be the accepted answer... I assume it's smart enough to use the cached metadata objects internally; either way, nice and concise and using .net's own methods – The Bearded Llama Apr 11 '19 at 10:38
  • 1
    Only available via System.Web.Mvc - not everybody does web apps, even in 2020.. – Yoda Apr 06 '20 at 09:51
9

Nice classes by Rich Tebb! I've been using DisplayAttribute and the code did not work for me. The only thing I've added is handling of DisplayAttribute. Brief search yielded that this attribute is new to MVC3 & .Net 4 and does almost the same thing plus more. Here's a modified version of the method:

 public static string GetPropertyDisplayString<T>(Expression<Func<T, object>> propertyExpression)
    {
        var memberInfo = GetPropertyInformation(propertyExpression.Body);
        if (memberInfo == null)
        {
            throw new ArgumentException(
                "No property reference expression was found.",
                "propertyExpression");
        }

        var displayAttribute = memberInfo.GetAttribute<DisplayAttribute>(false);

        if (displayAttribute != null)
        {
            return displayAttribute.Name;
        }
        else
        {
            var displayNameAttribute = memberInfo.GetAttribute<DisplayNameAttribute>(false);
            if (displayNameAttribute != null)
            {
                return displayNameAttribute.DisplayName;
            }
            else
            {
                return memberInfo.Name;
            }
        }
    }
alex
  • 111
  • 1
  • 3
4

I have this generic utility method. I pass in a list of a given type (Assuming you have a supporting class) and it generates a datatable with the properties as column headers and the list items as data.

Just like in standard MVC, if you dont have DisplayName attribute defined, it will fall back to the property name so you only have to include DisplayName where it is different to the property name.

    public DataTable BuildDataTable<T>(IList<T> data)
    {
        //Get properties
        PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        //.Where(p => !p.GetGetMethod().IsVirtual && !p.GetGetMethod().IsFinal).ToArray(); //Hides virtual properties

        //Get column headers
        bool isDisplayNameAttributeDefined = false;
        string[] headers = new string[Props.Length];
        int colCount = 0;
        foreach (PropertyInfo prop in Props)
        {
            isDisplayNameAttributeDefined = Attribute.IsDefined(prop, typeof(DisplayNameAttribute));

            if (isDisplayNameAttributeDefined)
            {
                DisplayNameAttribute dna = (DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute));
                if (dna != null)
                    headers[colCount] = dna.DisplayName;
            }
            else
                headers[colCount] = prop.Name;

            colCount++;
            isDisplayNameAttributeDefined = false;
        }

        DataTable dataTable = new DataTable(typeof(T).Name);

        //Add column headers to datatable
        foreach (var header in headers)
            dataTable.Columns.Add(header);

        dataTable.Rows.Add(headers);

        //Add datalist to datatable
        foreach (T item in data)
        {
            object[] values = new object[Props.Length];
            for (int col = 0; col < Props.Length; col++)
                values[col] = Props[col].GetValue(item, null);

            dataTable.Rows.Add(values);
        }

        return dataTable;
    }

If there's a more efficient / safer way of doing this, I'd appreicate any feedback. The commented //Where clause will filter out virtual properties. Useful if you are using model classes directly as EF puts in "Navigation" properties as virtual. However it will also filter out any of your own virtual properties if you choose to extend such classes. For this reason, I prefer to make a ViewModel and decorate it with only the needed properties and display name attributes as required, then make a list of them.

Hope this helps.

Francis Rodgers
  • 4,565
  • 8
  • 46
  • 65
3
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);

foreach (PropertyDescriptor property in properties)
{
    if (property.Name == "Name")
    {
        Console.WriteLine(property.DisplayName); // Something To Name
    }
}

where foo is an instance of Class1

CarenRose
  • 1,266
  • 1
  • 12
  • 24
Foo
  • 4,206
  • 10
  • 39
  • 54
3

Assuming property as PropertyInfo type, you can do this in one single line:

property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().Single().DisplayName
Leonel Sanches da Silva
  • 6,972
  • 9
  • 46
  • 66
2

Late to the party I know.

I use this:

public static string GetPropertyDisplayName(PropertyInfo pi)
{
  var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
  return dp != null ? dp.DisplayName : pi.Name;
}

Hope this helps.

Raul Marquez
  • 948
  • 1
  • 17
  • 27
1

Try this code:

EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()

It will give you the value of data attribute Name.

Ali
  • 3,373
  • 5
  • 42
  • 54
Rafael
  • 966
  • 12
  • 22
1

This works, thanks to someone above:

foreach (PropertyInfo pi in properties)
{
    var propName = pi.Name;
    var dp = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
    if (dp != null)
    {
        propName = dp.DisplayName; 
    }
}
Connor Low
  • 5,900
  • 3
  • 31
  • 52
T Newc
  • 11
  • 1
1

if you're here for [Display(Name="")] below code might help:

var props = yourObject.GetType().GetProperties();
foreach (var item in props)
{
   string title = item.GetCustomAttributes(typeof(DisplayAttribute), true).Cast<DisplayAttribute>().SingleOrDefault()?.Name;
}
farhang67
  • 759
  • 2
  • 14
  • 27
1
PropertyInfo[] properties = typeof(T).GetProperties();
String displayName = null;
foreach (PropertyInfo pi in properties){
     var displayAttribute = pi.GetCustomAttribute(typeof(DisplayAttribute));
    if (displayAttribute != null)
                {
                    displayName = (displayAttribute as DisplayAttribute).GetName();
                }
            }
simonata
  • 21
  • 3
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 22 '21 at 12:15
0

Following Rich Tebb's and Matt Baker's answer, I wanted to use the ReflectionExtensions methods in a LINQ query, but it didn't work, so I've made this method for it to work.

If DisplayNameAttribute is set the method will return it, otherwise it will return the MemberInfo name.

Test method:

static void Main(string[] args)
{
    var lst = new List<Test>();
    lst.Add(new Test("coucou1", "kiki1"));
    lst.Add(new Test("coucou2", "kiki2"));
    lst.Add(new Test("coucou3", "kiki3"));
    lst.Add(new Test("coucou4", "kiki4"));
    lst.ForEach(i => 
        Console.WriteLine(i.GetAttributeName<Test>(t => t.Name) + ";" + i.GetAttributeName<Test>(t=>t.t2)));
}

Test method output:

Test method output

The class with DisplayName1 Attribute:

public class Test
{
    public Test() { }
    public Test(string name, string T2)
    {
        Name = name;
        t2 = T2;
    }
    [DisplayName("toto")]
    public string Name { get; set; }
    public string t2 { get; set; }
}

And the extension method:

public static string GetAttributeName<T>(this T itm, Expression<Func<T, object>> propertyExpression)
{
    var memberInfo = GetPropertyInformation(propertyExpression.Body);
    if (memberInfo == null)
    {
        throw new ArgumentException(
            "No property reference expression was found.",
            "propertyExpression");
    }

    var pi = typeof(T).GetProperty(memberInfo.Name);
    var ret = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault();
    return ret != null ? ret.DisplayName : pi.Name;

}

CarenRose
  • 1,266
  • 1
  • 12
  • 24
Xavave
  • 645
  • 11
  • 15
  • `GetPropertyInformation()` does not exist in this context. I've just realised that this code is present in an [answer](https://stackoverflow.com/a/5015911/6236042) below – devklick Jan 07 '19 at 21:37
0

Please try below code, I think this will solve your problem.

var classObj = new Class1();
classObj.Name => "StackOverflow";

var property = new Class1().GetType().GetProperty(nameof(classObj.Name));
var displayNameAttributeValue = (property ?? throw new InvalidOperationException())
    .GetCustomAttributes(typeof(DisplayNameAttribute)) as DisplayNameAttribute; 

if (displayNameAttributeValue != null)
{
   Console.WriteLine("{0} = {1}", displayNameAttributeValue, classObj.Name);
}
CarenRose
  • 1,266
  • 1
  • 12
  • 24
Sid
  • 111
  • 1
  • 7
0

If instead

[DisplayName("Something To Name")]

you use

[Display(Name = "Something To Name")]

Just do this:

private string GetDisplayName(Class1 class1)
{
    string displayName = string.Empty;

    string propertyName = class1.Name.GetType().Name;

    CustomAttributeData displayAttribute = class1.GetType().GetProperty(propertyName).CustomAttributes.FirstOrDefault(x => x.AttributeType.Name == "DisplayAttribute");

    if (displayAttribute != null)
    {
        displayName = displayAttribute.NamedArguments.FirstOrDefault().TypedValue.Value;
    }

    return displayName;
}
MarchalPT
  • 1,268
  • 9
  • 28