提交已删除第一个项目的项目列表将删除所有项目

时间:2013-09-23 11:09:23

标签: forms asp.net-mvc-4 defaultmodelbinder

我有一个包含子项列表的模型,如下所示:

class MyObj {
    public string Name {get;set;}
    public List<mySubObject> Items {get;set;} 
}

class mySubObject { 
    public string Name {get;set;}
    public int Order {get;set;}
}

现在,当我使用for循环和editorFor渲染列表时,我得到的html就像这样:

<input type="text" name="Items[0].Name">
<input type="Number" name="Items[0].Order">
<input type="text" name="Items[1].Name">
<input type="number" name="Items[1].Order">
...
<input type="text" name="Items[9].Name">
<input type="number" name="Items[9].Order">

现在想象一下通过jQuery从HTML中删除第一个元素,因为我不再想要它在我的列表中,然后保存列表。返回的数据没有第一个[0]元素 并且从1到9的所有元素都会转到服务器,但模型绑定失败,并且(在服务器上)显示项目列表为null

我做错了什么?

这是默认模型绑定器的错误吗?

1 个答案:

答案 0 :(得分:0)

  

我做错了什么?

在指数中留下空洞。

  

这是默认模型绑定器的错误吗?

不,这是设计上的。你不应该在指数上留下任何漏洞。

一种可能性是在删除行时重新计算索引,但是你必须为此编写大量的垃圾javascript。

我建议你使用不同的方法。而不是使用顺序索引使用Guids。 Phil Haack在以下博客文章中详细介绍了这种方法:http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx(非顺序索引部分)。

Steven Sanderson在这篇文章中说明了一个很好的小帮手,可以让你轻松实现这个目标:http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

你可以这样使用:

@using(Html.BeginCollectionItem("Items")) 
{
    for (var i = 0; i < Model.Items.Count; i++)
    {
        @Html.EditorFor(x => x.Name)
        @Html.EditorFor(x => x.Order)
    }
}

它将生成以下内容:

<input type="hidden" name="Items.Index" value="F769E33C-4D07-4586-8D9C-63D386C641FA" />
<input type="text" name="Items[F769E33C-4D07-4586-8D9C-63D386C641FA].Name">
<input type="Number" name="Items[F769E33C-4D07-4586-8D9C-63D386C641FA].Order">

<input type="hidden" name="Items.Index" value="F4A4A9BB-4427-497E-BFD5-3CDE1F46095B" />
<input type="text" name="Items[F4A4A9BB-4427-497E-BFD5-3CDE1F46095B].Name">
<input type="number" name="Items[F4A4A9BB-4427-497E-BFD5-3CDE1F46095B].Order">

...

现在可以随意使用javascript在客户端上添加/删除行,而不必担心它会破坏您的集合的模型绑定。