EnumDropDownListFor使用Reflection抛出“返回类型'System.Object'不受支持。”

时间:2015-02-25 17:33:13

标签: c# asp.net asp.net-mvc razor html-helper

我正在尝试使用反射构建设置页面。一些选项是枚举,但标准@Html.EditorFor()给出了一个文本框而不是这些属性的下拉列表。我有一种使用@Html.DropDownList()进行排序的方法,但我希望“for”帮助程序能够获得预先选择值的好处。

public class CycleSettings
{
    //a bunch of sub-objects, like:
    public SurveyConfiguration Survey { get; set; }
}

public class SurveyConfiguration
{
    [JsonConverter(typeof(StringEnumConverter))]
    [DisplayName("Display Survey Data")]
    public DataDisplayFullOptions Data { get; set; }
}

public enum DataDisplayFullOptions
{
    Available,
    [Display(Name = "Coming Soon")]
    ComingSoon,
    Report
}

视图

@foreach (var property in typeof(CycleSettings).GetProperties()) {
    object temp = property.GetValue(Model.Settings.CycleSettings[Model.CurrentYear][Model.CurrentCycle]);
    @Html.Label(property.Name)
    <div style="padding-left: 20px">
        @foreach (var subprop in temp.GetType().GetProperties())
        {
            object temp2 = subprop.GetValue(temp);
            var label = Attribute.GetCustomAttribute(subprop, typeof (DisplayNameAttribute));
            @Html.Label(label != null ? ((DisplayNameAttribute)label).DisplayName : subprop.Name,new {@style="padding-right: 20px"})
            @(temp2.GetType().IsEnum ? Html.EnumDropDownListFor((m) => temp2) : Html.EditorFor((m) => temp2)) //error occurs here on EnumDropDownListFor path
            /*Html.DropDownList(subprop.Name, EnumHelper.GetSelectList(temp2.GetType()))*/ //this worked, but I am trying to use the EnumDropDownListFor to get the correct property selected on load
            <br/>
        }
    </div>
}

堆栈跟踪

  

[ArgumentException:不支持返回类型'System.Object'。   参数名称:表达式

  System.Web.Mvc.Html.SelectExtensions.EnumDropDownListFor(HtmlHelper`1   htmlHelper,Expression`1表达式,String optionLabel,IDictionary`2   htmlAttributes)+1082
  System.Web.Mvc.Html.SelectExtensions.EnumDropDownListFor(HtmlHelper`1   htmlHelper,Expression`1表达式,String optionLabel)+90

编辑:刚试过这个 - 没有更多错误,但仍未选择正确的值:

Html.DropDownListFor((m) => temp2, EnumHelper.GetSelectList(temp2.GetType()))

2 个答案:

答案 0 :(得分:2)

答案结果非常简单。我接近这个尝试:

Html.DropDownListFor((m) => temp2, EnumHelper.GetSelectList(temp2.GetType()))

我只需要override GetSelectList

Html.DropDownListFor((m) => temp2, EnumHelper.GetSelectList(temp2.GetType(), (Enum)temp2))

答案 1 :(得分:0)

这是我经常使用的枚举扩展。希望它可以提供帮助。

public enum Gender
{
    [EnumDescription("Not selected")]
    NotSelected,
    [EnumDescription("Male")]
    Male,
    [EnumDescription("Female")]
    Female
}

在您的视图中(您可以省略“数据绑定”Knockout绑定)

@Html.DropDownList(
    "gender",
    SelectListExt.ToSelectList(typeof(Gender)),
    new
    {
        data_bind = "value: Gender",
    })

选择列表助手类:

public static class SelectListExt
{
    public static SelectList ToSelectList(Type enumType)
    {
        return ToSelectList(enumType, String.Empty);
    }

    public static SelectList ToSelectList(Type enumType, string selectedItem)
    {
        List<SelectListItem> items = new List<SelectListItem>();

        foreach (var item in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(item.ToString());
            var attribute = fi.GetCustomAttributes(typeof(EnumDescription), true).FirstOrDefault();
            var title = attribute == null ? item.ToString() : ((EnumDescription)attribute).Text;

            // uncomment to skip enums without attributes
            //if (attribute == null)
            //    continue;

            var listItem = new SelectListItem
            {
                Value = ((int)item).ToString(),
                Text = title,
                Selected = selectedItem == ((int)item).ToString()
            };
            items.Add(listItem);
        }

        return new SelectList(items, "Value", "Text", selectedItem);
    }
}

属性本身:

public class EnumDescription : Attribute
{
    public string Text { get; private set; }

    public EnumDescription(string text)
    {
        this.Text = text;
    }
}

您还可以使用我的扩展类将枚举转换为字符串描述:

public static class EnumExtensions
{
    public static string ToDescription(this Enum enumeration)
    {
        Type type = enumeration.GetType();
        MemberInfo[] memInfo = type.GetMember(enumeration.ToString());

        if (null != memInfo && memInfo.Length > 0)
        {
            object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumDescription), false);
            if (null != attrs && attrs.Length > 0)
                return ((EnumDescription)attrs[0]).Text;
        }
        else
        {
            return "0";
        }

        return enumeration.ToString();
    }
}

此代码并不完美,但它适用于我。随意重构和发布更新!