Search code examples
c#asp.netasp.net-mvcrazorhtml-helper

EnumDropDownListFor using Reflection throwing "Return type 'System.Object' is not supported."


I'm trying to build out a settings page using reflection. Some options are enums, but the standard @Html.EditorFor() gives a text box rather than a dropdown on these properties. I have an approach sort-of working using @Html.DropDownList(), but I want the "for" helper to get the benefits of having the value pre-selected.

Classes

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
}

View

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

Stack Trace

[ArgumentException: Return type 'System.Object' is not supported. Parameter name: expression]
System.Web.Mvc.Html.SelectExtensions.EnumDropDownListFor(HtmlHelper`1 htmlHelper, Expression`1 expression, String optionLabel, IDictionary`2 htmlAttributes) +1082
System.Web.Mvc.Html.SelectExtensions.EnumDropDownListFor(HtmlHelper`1 htmlHelper, Expression`1 expression, String optionLabel) +90

EDIT: Just tried this-- no more error, but still not selecting the right value:

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

Solution

  • The answer turned out to be pretty simple. I was close with this attempt:

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

    I just needed to override the GetSelectList:

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