C# MVC5 @Html.EnumDropDownListFor 在 "postback" 上失去选择

C# MVC5 @Html.EnumDropDownListFor loses selection on "postback"

MVC5 EF6

我有一个产品。一个产品可以有多个标题,一个标题有一个枚举类型。

我正在为产品创建视图 - 模型就是产品

查看:

            @for (int x = 0; x < Model.ProdTitles.Count; x++)
            {                    
                <tr>
                    <td>
                        @Html.TextBoxFor(model => model.ProdTitles.ToArray()[x].Title, new { @class = "form-control" })
                        @Html.ValidationMessageFor(model => model.ProdTitles.ToArray()[x].Title, "", new { @class = "text-danger" })
                    </td>
                    <td>
                        @Html.EnumDropDownListFor(model => model.ProdTitles.ToArray()[x].TitleTypeID, new { @class = "form-control" })
                    </td>
                    <td>
                        @Html.EnumDropDownListFor(model => model.ProdTitles.ToArray()[x].CultureID, new { @class = "form-control" })
                    </td>
                </tr>
            }

在 Controller 中 - 当我创建一个产品以 return 到视图时,我为每种标题类型创建一个标题并将其添加到产品中。视图显示了我所期望的一切。

当我点击“创建”按钮时,产品和标题按预期 return 发送到控制器并且我验证了标题(不同的验证取决于类型)。我将任何错误添加到 ModelState,因此,ModelState.IsValid 是错误的。

我return回到视图return View(product); 调试此产品,所有标题都在产品中并且它们仍然具有正确的类型,但视图现在显示列表中的第一个枚举,用于所有标题而不是模型中实际存在的标题!

如果我将 EnumDropDown 更改为文本框,则会显示正确的类型,因此模型绝对正确:

我不确定为什么会这样,我希望有人可以提出修复建议?它是 EnumDropDownFor 中的错误吗?还是我做错了什么?

控制器代码:

    public ActionResult Create()
    {
        Product product = new Product();

        foreach (var enm in Utils.Enums.EnumHelper.GetValues<Utils.Enums.TitleType>())
        {
            product.ProdTitles.Add(new ProdTitle()
            {
                CultureID = Utils.Enums.CultureID.English_United_Kingdom,                    
                DateCreated = DateTime.Now,
                Title = "",
                TitleTypeID = enm
            });
        }

        return View(product);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "ProdID,DateCreated")] Product product, ICollection<ProdTitle> prodTitles)
    {
        //ensure titles are all valid before saving
        for (int x = 0; x < prodTitles.Count; x++)
        {
            ProdTitle title = prodTitles.ToArray()[x];
            if (!title.IsValid)
            {
                ModelState.AddModelError(string.Empty, title.TitleTypeID + " title is invalid.");
            }
            product.ProdTitles.Add(title);
        }


        if (ModelState.IsValid)
        {
            db.Products.Add(product);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(product);
    }

ProdTitle 型号

public partial class ProdTitle
{
    public long TitleID { get; set; }
    public long ProdID { get; set; }
    public Utils.Enums.TitleType TitleTypeID { get; set; }
    public string Title { get; set; }
    public Utils.Enums.CultureID CultureID { get; set; }
    public System.DateTime DateCreated { get; set; }

    public virtual Product Product { get; set; }
    public virtual DataSource DataSource { get; set; }
}

处理集合中的下拉列表时,您需要自定义 EditorTemplate

/Views/Shared/EditorTemplates/ProdTitle.cshtml

@model yourAssembly.ProdTitle

<tr>
  <td>
    @Html.TextBoxFor(m => m.Title, new { @class = "form-control" })
    @Html.ValidationMessageFor(m => m.Title, new { @class = "text-danger" })
  </td>
  <td>
    @Html.EnumDropDownListFor(m => m.TitleTypeID, new { @class = "form-control" })
  </td>
  <td>
    @Html.EnumDropDownListFor(m => m.CultureID, new { @class = "form-control" })
  </td>
</tr>

然后在主视图

@model yourAssembly.Product
@using(Html.BeginForm())
{
  .... // other controls for properties of Product
  @Html.EditorFor(m => m.ProdTitles) // not in a loop!
}

然后修改控制器为

public ActionResult Create(Product product)

注意:您当前的 [Bind] 属性将 ProdTitle 属性 排除在绑定之外,并且在任何情况下您都应该使用视图模型来仅表示您想要 display/edit