关于asp.net mvc:视图中渲染的MVC模型数据回发时为空

MVC model data that is rendered in the view is null when posted back

我已经看到了类似的问题,并遵循了常规答案,即确保所有模型数据都以 HTML 格式呈现。

我已经这样做了,模型在视图中使用@Html.HiddenFor() 呈现,但是当回发到控制器时列表中没有项目?

视图会愉快地渲染列表中的多个项目,但是发布的数据中的List<Item> Items始终是一个空列表(非空)

型号

1
2
3
4
5
6
7
8
9
10
11
12
public class ItemCollection
{
    public List<string> AvailiableActions { get; set; }
    public List<Item> Items { get; set; }
}

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string SelectedAction { get; set; }
}

查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@model ItemCollection
@using (Html.BeginForm("myAction","myController", FormMethod.Post))
{
    <fieldset>
       
            @Html.HiddenFor(m => Model.Items)
            @Html.DisplayNameFor(x => x.AvailiableActions)
            <table>
                @{
                    foreach (var item in Model.Items)
                    {
                        @Html.HiddenFor(m => item)
                        @Html.HiddenFor(s => item.Id)
                        <tr>
                            <td>@item.Name</td>
                            <td>@Html.DropDownList(item.SelectedAction, new SelectList(Model.AvailiableActions))</td>
                        </tr>
                    }
                }                  
            </table>
       
    </fieldset>
}

控制器

1
2
3
4
5
6
7
8
    [HttpPost]
    private ActionResult myAction(ItemCollection model)
    {
        if (model.Items.Count() == 0)
        {
            // this is true.. something is wrong......
        }
    }


您可以考虑使用 EditorTemplates(其他站点上的示例),而不是遍历所有项目以确保将索引添加到生成的输出中。

EditorTemplates 允许您为 \\Views\\Shared\\EditorTemplates\\Item.cshtml 中的单个 item 指定模板:

1
2
3
4
5
6
7
8
9
10
11
@model Item
@{
    var options= (List<string>)ViewData["Options"];
 }
 <tr>
     <td>
         @Html.HiddenFor(m => m.Id)
          @Html.DisplayFor(m => m.Name)
     </td>
     <td>@Html.DropDownList(m => m.SelectedAction, new SelectList(options))</td>
 </tr>

那么您可以简单地将您的视图更改为:

1
2
3
4
5
6
7
8
9
10
11
@model ItemCollection
@using (Html.BeginForm("myAction","myController", FormMethod.Post))
{
    <fieldset>
       
            <table>
                @Html.EditorFor(m => m.Items, new {Options = Model.AvailiableActions })
            </table>
       
    </fieldset>
}


您不能使用 foreach 循环来呈现集合的控件。它呈现重复的 idname 属性,而不需要绑定到集合的索引器。使用 for 循环

1
2
3
4
5
6
7
8
9
10
for (int i = 0; i < Model.Items.Count; i++)
{
  <tr>
    <td>
      @Html.HiddenFor(m => m.Items[i].Id)
      @Html.DisplayFor(m => m.Items[i].Name)
    </td>
    <td>@Html.DropDownList(m => m.Items[i].SelectedAction, new SelectList(Model.AvailiableActions))</td>
  </tr>
}

请注意,您的视图还包括 @Html.HiddenFor(m => Model.Items)@Html.HiddenFor(m => item),它们也会失败,因为 item 是一个复杂的对象,您只能绑定到值类型。您需要同时删除两者。