Peter Hubert
Peter Hubert

Reputation: 95

Enum [Display(Name) localisation MVC 4

I have a enum that holds countries:

public enum CountryEnum
{
    [Display(Name = "AF", ResourceType = typeof(Global))]
    AF,

    [Display(Name = "AL", ResourceType = typeof(Global))]
    AL,

    [Display(Name = "DZ", ResourceType = typeof(Global))]
    DZ,
};

As you can see I make use of the DataAnnotations to localise the values.

Now I want to display a dropdownlist with all of the localised country names. I come up with this code:

public static string GetDisplayName<TEnum>(TEnum value)
{        
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DisplayAttribute[] attributes = 
        (DisplayAttribute[])fi.GetCustomAttributes(
            typeof(DisplayAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
            return attributes[0].Name;
        else
            return value.ToString();
}

I have a Html helper that makes use of the above method:

public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
{
    ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    Type enumType = GetNonNullableModelType(metadata);
    IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

    IEnumerable<SelectListItem> items = from value in values
                                        select new SelectListItem
                                        {
                                            Text = GetDisplayName(value),
                                            Value = value.ToString(),
                                            Selected = value.Equals(metadata.Model)
                                        };

    // If the enum is nullable, add an 'empty' item to the collection
    if (metadata.IsNullableValueType)
        items = SingleEmptyItem.Concat(items);

    return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
}

The DropDown renders correctly, however, GetDisplayName doesn't return the localised value, it just display the name attribute (e.g. AF for the first entry).

How can I modify GetDisplayName method to return the localised value?

Upvotes: 0

Views: 2159

Answers (2)

Carlos Casalicchio
Carlos Casalicchio

Reputation: 162

I was having a similar problem, having setup the Display Attribute as you did (easier since classes use the same attribute to load localizations), so took your initial code and tweaked it a bit, now it is displaying the localization string as expected. I don't think it is the most clever or optimized way of doing it, but it works. Hopefully that's what you intended.

public static string GetDisplayName<TEnum>(TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DisplayAttribute[] attributes = (DisplayAttribute[])fi.
            GetCustomAttributes(typeof(DisplayAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
        {
            string key = attributes[0].Name;
            string localizedString = attributes[0].ResourceType.GetProperty(key).GetValue("").ToString();
            return localizedString;
        }
        else
            return value.ToString();
    }

Upvotes: 0

Benjamin Gale
Benjamin Gale

Reputation: 13177

You need to update your GetDisplayName method to use the GetName() method rather than the Name property of the DisplayAttribute.

Like this:

public static string GetDisplayName<TEnum>(TEnum value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DisplayAttribute[] attributes = (DisplayAttribute[])fi.
        GetCustomAttributes(typeof(DisplayAttribute), false);

    if ((attributes != null) && (attributes.Length > 0))
        return attributes[0].GetName();
    else
        return value.ToString();
}

From the MSDN documentation for DisplayAttribute.Name:

Do not use this property to get the value of the Name property. Use the GetName method instead.

The MSDN documentation for the GetName() method has this to say:

Returns the localized string for the Name property, if the ResourceType property has been specified and the Name property represents a resource key; otherwise, the non-localized value of the Name property.

Upvotes: 2

Related Questions