Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get [Display] attribute value from resource in MVC

I have used the [Display] attribute for one of my enums:

    public enum eCommentType
    {
        [Display(ResourceType = typeof(FaultManagementStrings), Name = "NormalComment")]
        NormalComment = 0,

        [Display(ResourceType = typeof(FaultManagementStrings), Name = "OpenningComment")]
        OpenningComment = 1,

        [Display(ResourceType = typeof(FaultManagementStrings), Name = "StartProgressComment")]
        StartProgressComment = 2,

        [Display(ResourceType = typeof(FaultManagementStrings), Name = "ClouserComment")]
        ClouserComment = 3,

        [Display(ResourceType = typeof(FaultManagementStrings), Name = "ReopennignComment")]
        ReopennignComment = 4
    }

Is it possible to create an Extention method that will reuse the exsisting MVC finctionallity of getting the Display attribute value from the specified resource ?

I would what something like that...

@Html.GetEnumDisplayAttributeValue(c=> comment.CommentType)

I know i could wirte something that will implement the required reflection and find the value of the resource type and the call resource manager and so on... but i think that maybe it is possible to use the exsisting built in functionally of mvc.. after all it is already done when you call a LabelFor helper.

is is possible or should i reinvent the wheel ?

like image 298
Mortalus Avatar asked May 15 '13 12:05

Mortalus


1 Answers

I have had the same problem and created these extension methods:

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;

public static class EnumHelper
{
    private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = string.Empty, Value = string.Empty } };

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return htmlHelper.EnumDropDownListFor(expression, null);
    }

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

        var items =
            values.Select(value => new SelectListItem
                                       {
                                           Text = GetName(value),
                                           Value = value.ToString(),
                                           Selected = value.Equals(metadata.Model)
                                       });

        if (metadata.IsNullableValueType)
        {
            items = SingleEmptyItem.Concat(items);
        }

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

    private static string GetName<TEnum>(TEnum value)
    {
        var displayAttribute = GetDisplayAttribute(value);

        return displayAttribute == null ? value.ToString() : displayAttribute.GetName();
    }

    private static DisplayAttribute GetDisplayAttribute<TEnum>(TEnum value)
    {
        return value.GetType()
                    .GetField(value.ToString())
                    .GetCustomAttributes(typeof(DisplayAttribute), false)
                    .Cast<DisplayAttribute>()
                    .FirstOrDefault();
    }

    private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
    {
        var realModelType = modelMetadata.ModelType;
        var underlyingType = Nullable.GetUnderlyingType(realModelType);

        return underlyingType ?? realModelType;
    }
}

You can use these extension methods in your views as follows:

@Html.EnumDropDownListFor(c=> comment.CommentType)

You should now see a dropdownlist containing the enum values' names according to their DisplayAttribute.

The actual retrieval of the displayed enum value is done in the GetName method, which first uses the GetDisplayAttribute method to try to retrieve the DisplayAttribute of the enum value. If the enum value was indeed decorated with a DisplayAttribute, it will use that to retrieve the name to be displayed. If there is no DisplayAttribute, we just return the name of the enum value.

like image 188
Erik Schierboom Avatar answered Oct 31 '22 11:10

Erik Schierboom