@ Html.EnumDropDownListFor - 未设置下拉值

时间:2015-11-14 12:44:06

标签: c# asp.net enums asp.net-mvc-5

我有一个基本表单,允许用户输入详细信息然后发布并保存到数据库 - 这可以正常工作而没有任何问题:

@model R32.Register.Models.RegisterCar
@{
    ViewBag.Title = "Edit Your R32";
}

<h2>Edit R32</h2>
<div>
    @using (Html.BeginForm("UpdateCar", "Garage", FormMethod.Post))
    {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Enter details</legend>
            <ol>                   
                <li>
                    @Html.LabelFor(m => m.NumberPlate)
                    @Html.EditorFor(m => m.NumberPlate, new { @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.NumberPlate)
                </li>                    
                <li>
                    @Html.LabelFor(m => m.Edition)
                    @Html.EnumDropDownListFor(m => m.Edition, "Select an edition:", new { @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.Edition)
                </li>
                <li>
                    @Html.LabelFor(m => m.Colour)
                    @Html.EnumDropDownListFor(m => m.Colour, "Select a colour:", new { @class = "form-control" })
                    @Html.ValidationMessageFor(m => m.Colour)
                </li>                    
            </ol>
            <input type="submit" value="Save Changes" />
        </fieldset>
    }
</div>

模型摘要:

[Required]
[Display(Name="Edition")]
public MkEnum? Edition { get; set; }

枚举:

public enum MkEnum
{
    [Display(Name="Mk4")]
    Mk4 = 1,
    [Display(Name="Mk5")]
    Mk5 = 2
}

控件按预期呈现,版本下拉列表包含三个值:“选择版本”,“Mk4”和“Mk5”。

用户可以选择版本,控制已经过验证,然后发布到控制器。

邮件成功,所有选定的值都会发送到控制器 - 然后应用程序将数据保存在数据库中,依此类推,没有任何问题。

问题是当我将此模型传回同一个视图以允许用户编辑已保存的数据时,枚举的已保存值未被设置为下拉列表中的选定值。

我可以确认任何已保存的字符串值(例如本例中的NumberPlate)都会被传回视图并加载到UI中。

在渲染时在viewmodel上设置断点我可以确认我的@model包含枚举属性的保存值 - 例如版本 - 但最终结果是渲染了“选择版本:”下拉列表包含预期的下拉值,但它的值是默认的“选择一个版本:”而不是传入的实际值。 m.Edition。

我已经能够使用DropDownListFor来解决这个问题 - 但是我很难理解为什么使用EnumDropDownListFor无效,因为这显然是一个更优雅的解决方案。

有人对此有任何帮助/建议吗?

2 个答案:

答案 0 :(得分:0)

我自己也遇到了这个问题。发生这种情况是因为枚举类型的字段被传递回序列化为枚举名称的浏览器,但@ Html.EnumDropDownListFor将其选项值作为整数生成。浏览器无法匹配两者,因此下拉列表保持默认选择。

有三种方法可以解决这个问题。

  1. 获取视图模型的枚举字段以正确地序列化为int。
  2. 编写一个使用枚举名称作为选项值的下拉生成器。
  3. 使用javascript手动选择选项(此处包括剃刀语法)

    $("#YourDropdownID option").each(function () {
        if ($(this).html() == '@(Html.DisplayFor(o => o.YourEnumFieldName))') {
            $(this).attr("selected", "selected");
            return;
        }
    });

答案 1 :(得分:0)

好的,所以从我看到的问题是由使用ActionLink传回正在编辑的项目的完整模型引起的。所有内容都在Query字符串中发回,因此我的Enum值以下列方式传递给控制器​​:mkEnum = Mk4。

然后我在我的示例中加载了UpdateCar视图,但查询字符串值在回调到视图时仍然存在。

EnumDropDownListFor无法将枚举的文本值解释/转换为实际值 - 如果我手动将查询字符串编辑为mkEnum = 1,则将正确的值载入ViewModel。

除了这个问题,将整个模型传回控制器也不是一个好的解决方案。 我已修改代码以传回正在编辑的项目的单个Id - 然后控制器验证用户是否可以访问该Id,从数据库中检索模型然后将其传递回与上面示例中相同的视图。

通过此次更改,我的下拉列表现在正在更新其值而没有任何问题。

TLDR;如果遇到此问题,请检查以确保在加载视图和使用EnumDropDownListFor时,在查询字符串中没有模型属性(特别是由其字符串值表示的枚举值)。