从MVC中的资源获取[Display]属性值

时间:2013-05-15 12:00:22

标签: asp.net-mvc asp.net-mvc-3 reflection data-annotations html-helper

我在其中一个枚举中使用了[Display]属性:

    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
    }

是否可以创建一个Extention方法,该方法将重用从指定资源获取Display属性值的现有MVC功能?

我会是那样的......

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

我知道我可以用一些东西来实现所需的反射并找到资源类型和调用资源管理器等的值...但我认为也许可以使用现有的内置函数mvc ..毕竟当你打电话给LabelFor帮助时已经完成了。

是可能还是应该重新发明轮子?

2 个答案:

答案 0 :(得分:5)

我遇到了同样的问题并创建了这些扩展方法:

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

您可以在视图中使用这些扩展方法,如下所示:

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

您现在应该会看到一个下拉列表,其中包含根据DisplayAttribute的枚举值名称。

显示的枚举值的实际检索是在GetName方法中完成的,该方法首先使用GetDisplayAttribute方法尝试检索枚举值的DisplayAttribute。如果枚举值确实用DisplayAttribute修饰,它将使用它来检索要显示的名称。如果没有DisplayAttribute,我们只返回枚举值的名称。

答案 1 :(得分:1)

正如预期的那样,Microsoft在MVC 5.1(RC1)中添加了EnumDropDownListFor HTML帮助程序方法。