About Enum and DataAnnotation

developer033 picture developer033 · May 26, 2015 · Viewed 14.7k times · Source

I have this Enum (Notebook.cs):

public enum Notebook : byte
{
   [Display(Name = "Notebook HP")]
   NotebookHP,

   [Display(Name = "Notebook Dell")]
   NotebookDell
}

Also this property in my class (TIDepartment.cs):

public Notebook Notebook { get; set; }

It's working perfectly, I just have one "problem":

I created an EnumDDLFor and it's showing the name I setted in DisplayAttribute, with spaces, but the object doesn't receive that name in DisplayAttribute, receives the Enum name (what is correct), so my question is:

Is there a way to receive the name with spaces which one I configured in DisplayAttribute?

Answer

akousmata picture akousmata · May 26, 2015

MVC doesn't make use of the Display attribute on enums (or any framework I'm aware of). You need to create a custom Enum extension class:

public static class EnumExtensions
{
    public static string GetDisplayAttributeFrom(this Enum enumValue, Type enumType)
    {
        string displayName = "";
        MemberInfo info = enumType.GetMember(enumValue.ToString()).First();

        if (info != null && info.CustomAttributes.Any())
        {
            DisplayAttribute nameAttr = info.GetCustomAttribute<DisplayAttribute>();
            displayName = nameAttr != null ? nameAttr.Name : enumValue.ToString();
        }
        else
        {
            displayName = enumValue.ToString();
        }
        return displayName;
    }
}

Then you can use it like this:

Notebook n = Notebook.NotebookHP;
String displayName = n.GetDisplayAttributeFrom(typeof(Notebook));

EDIT: Support for localization

This may not be the most efficient way, but SHOULD work.

public static class EnumExtensions
{
    public static string GetDisplayAttributeFrom(this Enum enumValue, Type enumType)
    {
        string displayName = "";
        MemberInfo info = enumType.GetMember(enumValue.ToString()).First();

        if (info != null && info.CustomAttributes.Any())
        {
            DisplayAttribute nameAttr = info.GetCustomAttribute<DisplayAttribute>();

            if(nameAttr != null) 
            {
                // Check for localization
                if(nameAttr.ResourceType != null && nameAttr.Name != null)
                {
                    // I recommend not newing this up every time for performance
                    // but rather use a global instance or pass one in
                    var manager = new ResourceManager(nameAttr.ResourceType);
                    displayName = manager.GetString(nameAttr.Name)
                }
                else if (nameAttr.Name != null)
                {
                    displayName = nameAttr != null ? nameAttr.Name : enumValue.ToString();
                }
            }
        }
        else
        {
            displayName = enumValue.ToString();
        }
        return displayName;
    }
}

On the enum, the key and resource type must be specified:

[Display(Name = "MyResourceKey", ResourceType = typeof(MyResourceFile)]