处理回发数据中的数组 – MVC3

我现在是一个试图转向MVC的WebForms开发人员。 我对MVC非常兴奋,我真的很开心,但我遇到了一个奇怪的问题。 所以我要做的是为“小部件”创建一个高级编辑器。 我已经发布了以下代码。

添加前4-5项时,一切似乎都能正常工作,但删除第二项时会出现问题。 这是一个视觉示例。

首先添加4个值。

在此处输入图像描述

但是当我们删除第二个值时会出现问题。 我们最终得到了……

在此处输入图像描述

我似乎无法理解的是,为什么此属性在以下两行代码之间有所不同。

@Model.Values[i] @Html.TextBoxFor(m => m.Values[i]) 

我的猜测是@Model和(m => m)不引用同一个对象?

这是我的小部件类。

 public class Widget { #region Constructor public Widget() { ID = 0; Name = string.Empty; Values = new List(); } #endregion #region Properties [Required] [Display(Name = "ID")] public int ID { get; set; } [Required] [Display(Name = "Name")] public string Name { get; set; } [Required] [Display(Name = "Values")] public List Values { get; set; } #endregion } 

我的控制器看起来像这样。

 public ViewResult EditWidget(int id) { return View(_widgets.GetWidgetByID(id)); } [HttpPost] public ActionResult EditWidget(Widget widget) { if (!TryUpdateModel(widget)) { ViewBag.Message = "Error..."; return View(widget); } if (Request.Form["AddWidgetValue"] != null) { widget.Values.Add(Request.Form["TextBoxWidgetValue"]); return View("EditWidget", widget); } if (Request.Form["DeleteWidgetValue"] != null) { widget.Values.Remove(Request.Form["ListBoxWidgetValues"]); return View("EditWidget", widget); } _widgets.UpdateWidget(widget); _widgets.Save(); return RedirectToAction("Index"); } 

最后我的看法。

 @model MvcTestApplication.Models.Widget @{ ViewBag.Title = "EditWidget"; } 

EditWidget

@using (Html.BeginForm()) { @Html.ValidationSummary(true)
Widget @Html.HiddenFor(model => model.ID)
@Html.LabelFor(model => model.Name)
@Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name)
@for (var i = 0; i m.Values[i]) @Html.HiddenFor(m => m.Values[i])
} @Html.ListBox("ListBoxWidgetValues", new SelectList(Model.Values), new { style = "width: 100%" })
@Html.TextBox("TextBoxWidgetValue", string.Empty, new { style = "width: 100%" })

}
@Html.ActionLink("Back to List", "Index")

发生这种情况的原因是因为HTML帮助程序首先在绑定时查看ModelState发布的值,然后在模型中查看。 这意味着如果在POST控制器操作中,您尝试修改某个值,并且此相同的值是初始发布请求的一部分,HTML帮助程序将使用初始值而不是您修改的值。

例如,在您的EditWidget操作中,您执行此操作:

 if (Request.Form["DeleteWidgetValue"] != null) { widget.Values.Remove(Request.Form["ListBoxWidgetValues"]); return View("EditWidget", widget); } 

您应该从模型状态中删除最初发布的值:

 if (Request.Form["DeleteWidgetValue"] != null) { var itemToRemove = Request.Form["ListBoxWidgetValues"]; var index = widget.Values.IndexOf(itemToRemove); ModelState.Remove("Values[" + index + "]"); widget.Values.Remove(itemToRemove); return View("EditWidget", widget); } 

所以POST请求包含:

 Values[0] = 1 Values[1] = 2 Values[2] = 3 Values[3] = 4 

在POST操作中,您删除了例如第二个项目,因此您还应该将其从模型状态中删除,否则TextBoxFor帮助程序仍将使用旧项目。

您可能还会发现以下博文有用。 它适用于ASP.NET MVC 2 WebForms,但将它改编为Razor是微不足道的。