Html.BeginForm不会发回整个数据

时间:2013-05-16 16:47:18

标签: c# asp.net-mvc-3 razor

我问过非常相似的问题,但现在我缩小了外部因素,现在我希望有人能够指出我做错了什么以及为什么我没有得到预期的结果。

在我的控制器中,我从数据库中获取数据:

List<MCS_DocumentFields> model = (List<MCS_DocumentFields>)DocumentFieldService.GetFieldsForDocument(documentId);

进行一些排序并将List传递给我的视图:

var finalModel = model
                .OrderBy(c => c.ContentTypeId)
                .ThenBy(c => c.RowNo)
                .ThenBy(c => c.ColumnNo)
                .ThenBy(c => c.MCS_Fields.Order)
                .ToList();
            return View(finalModel);

此时finalModel的类型为List<MCS_DocumentFields>

我的观点是:

@model List<DataAccess.MCS_DocumentFields>
@{
    ViewBag.Title = "Document";
}
<div id="drawForm">

@using (Html.BeginForm("ActionMethodName", "Forms"))
{
    <table border="1">
        @for (int i = 0; i < Model.Count; i++)
        {
            if (!string.IsNullOrEmpty(Model[i].FieldValue))
            {
                <tr>
                <td>
                @Html.DisplayFor(x => x[i].FieldValue)
                @Html.HiddenFor(x => x[i].FieldValue)
                @Html.HiddenFor(x => x[i].Id)
                </td>
                </tr>
            }
        }
    </table>
   <button type="submit">Submit</button>   
}
</div>

这是渲染,我在浏览器中看到大约15行数据。当我将数据提交给我的控制器时:

[HttpPost]
public ActionResult ActionMethodName(List<MCS_DocumentFields> collection)
{
    var test = collection;
    //Some other code
}

在视图中使用此特定代码,我从页面上呈现的15条记录中获取1条记录。

但是,如果我改变我的观点:

<table border="1">
        @for (int i = 0; i < Model.Count; i++)
        {
            if (Model[i].ContentTypeId == 1)
            {
                <tr>
                <td>
                @Html.DisplayFor(x => x[i].FieldValue)
                @Html.HiddenFor(x => x[i].FieldValue)
                @Html.HiddenFor(x => x[i].Id)
                </td>
                </tr>
            }
        }
    </table>

更具体一点 - if (Model[i].ContentTypeId == 1)我得到10条记录(这个ContentTypeId确实有10条记录)

如果我这样看法:

<table border="1">
        @for (int i = 0; i < Model.Count; i++)
        {

                <tr>
                <td>
                @Html.DisplayFor(x => x[i].FieldValue)
                @Html.HiddenFor(x => x[i].FieldValue)
                @Html.HiddenFor(x => x[i].Id)
                </td>
                </tr>
        }
    </table>

根本没有检查,只是迭代所有记录 - 我将所有记录(43)返回给我的控制器 - 没有遗漏任何东西。

这非常令人困惑 - 我正在使用一个单独的实体,只是检查不同的属性值并且每次都得到不同的结果。如果我根本不进行任何检查,那么我会把所有东西都归还......这可能导致这个......?

2 个答案:

答案 0 :(得分:3)

请查看this blog,特别是有关跳过数组索引以及发生这种情况时会发生什么的部分。

基本上,因为您只渲染集合中的某些项目,所以模型绑定由于缺少索引而失败。正如我在你对你的另一个问题的评论中所说的那样,你可以通过删除视图中的逻辑(它不属于任何地方)来提供更好的服务。

创建一个ViewModel,它只是一个简单的类。在该ViewModel中,为要显示的每个集合定义属性。在控制器中,将大集合拆分为较小的集合,并将它们分配给ViewModel中的属性。将ViewModel传递给View并编写非常简单的代码以显示其中包含的数据。

完成后,您视图中的循环将与上一个示例完全相同,并且一切都能正常运行。

答案 1 :(得分:2)

这是因为索引字段。您的列表可以正常工作,但ModelBinder会在索引的第一个间隙处停止。

请参阅Phil Haacked's blog了解如何解决问题:

<input type="hidden" name="products.Index" value="cold" />
<input type="text" name="products[cold].Name" value="Beer" />
<input type="text" name="products[cold].Price" value="7.32" />

cold您需要放置@i。请注意,这将导致已发布的列表折叠:如果未发布索引0的列表项,则下一个(例如1)将位于索引{{1} },但我看到你的0字段会处理这个问题。

话虽如此,我同意@Jason:当你确定你传递的模型是你要显示的模型时,你不会遇到这个问题;我在重新订购viewmodel客户端然后将其发回时遇到了这个问题。