对象列表的回发是Null

时间:2014-02-21 21:30:23

标签: c# asp.net-mvc razor model-binding

我有一个MVC 4博客应用程序,我正在尝试添加一个管理面板,允许管理员编辑/删除已注册的帐户。我有视图和模型,但我无法弄清楚为什么我的模型没有正确传达。这是我的代码:

首先,我的管理面板有一个简单的ViewModel。它只包含一个列表,该列表将包含Web应用程序的所有注册用户。

    public class AdminViewModel
    {

        public List<User> UserList { get; set; }
    }

这是我的控制器,它将用户作为列表提取并将其发送到管理员视图

[HttpGet]
     public ActionResult Admin()
        {
            AdminViewModel avm = new AdminViewModel();
            avm.UserList = Db.Users.ToList();
            return View(avm);
        }

然后,这是我的视图,显示所有帐户信息,删除链接以删除用户,以及一些复选框以更改用户的能力。

@using cpts483.Models.ViewModels
@using cpts483.Models

@model AdminViewModel

<h1>Admin Control Panel</h1>

@using (@Html.BeginForm("UpdateUsers", "Home", FormMethod.Post))
{ 
<table>
    <tr>
        <th></th>
        <th>Id</th>
        <th>Email</th>
        <th>First Name</th>
        <th>Last Name</th>
        <th>IsAdmin</th>
        <th>CanWriteArticles</th>
    </tr>
    <tbody>
        @foreach (User u in Model.UserList)
        {
            <tr>
                <td>
                    @Html.ActionLink("Delete", "DeleteUser", new {id = u.Id})
                </td>
                <td>@u.Id</td>
                <td>@u.Email</td>
                <td>@u.FirstName</td>
                <td>@u.LastName</td>
                <td>
                    @Html.CheckBoxFor(m => m.UserList.Find(us => us.Id == u.Id).IsAdmin)
                </td>
                <td>
                    @Html.CheckBoxFor(m => m.UserList.Find(us => us.Id == u.Id).CanWriteArticles)
                </td>
            </tr>
        }
    </tbody>
</table>
    <input type="submit" value="Save Changes" id="update-users-btn" />
}

现在,我认为这会将我的AdminViewModel.UserList绑定到DOM中的复选框,然后当提交表单时,相同的AdminViewModel将被发送到我的回发处理程序并使用更新的数据。但是,不是这样,下面的处理程序具有AdminViewModel参数,每次都为null。我在这里做错了什么?

[HttpPost]
        public ActionResult UpdateUsers(AdminViewModel avm) // THIS avm IS ALWAYS NULL
        {
            foreach (User u in avm.UserList)
            {
                Db.Users.Attach(u);
            }

            Db.SaveChanges();
            return RedirectToAction("Admin");
        }

3 个答案:

答案 0 :(得分:1)

我为你做了一个小型原型,检查出来 -

让您的模型如下所示。为简单起见,我忽略了一些属性。

public class AdminViewModel
{
    public List<User> UserList { get; set; }
}
public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public bool IsAdmin { get; set; }
}

然后控制器动作将呈现视图 -

    public ActionResult Index()
    {
        AdminViewModel model = new AdminViewModel();
        model.UserList = new List<User>();
        model.UserList.Add(new User() { FirstName = "Rami", IsAdmin = true, Id = 10 });
        model.UserList.Add(new User() { FirstName = "James", IsAdmin = false, Id = 20 });
        return View(model);
    }

然后您的视图应如下所示。我使用hiddenFields来保存一些文本属性。

@model MVC.Controllers.AdminViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Html.BeginForm("Submit", "Person", FormMethod.Post))
{

    <table>
        @for (int i = 0; i < Model.UserList.Count; i++)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => Model.UserList[i].Id)
                    @Html.HiddenFor(modelItem => Model.UserList[i].Id)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => Model.UserList[i].FirstName)
                    @Html.HiddenFor(modelItem => Model.UserList[i].FirstName)
                </td>
                <td>
                    @Html.CheckBoxFor(modelItem => Model.UserList[i].IsAdmin)
                </td>
            </tr>
        }
    </table>
    <input type="submit" value="Save" />
}

单击提交按钮时,将触发以下控制器操作 -

    public ActionResult Submit(AdminViewModel model)
    {
        return View();
    }

当你设置一个断点时,你可以看到你坚持模型如下 -

enter image description here

答案 1 :(得分:0)

好问题!你的问题在这里:

<td>
    @Html.CheckBoxFor(m => m.UserList.Find(us => us.Id == u.Id).IsAdmin)
</td>
<td>
    @Html.CheckBoxFor(m => m.UserList.Find(us => us.Id == u.Id).CanWriteArticles)
</td>

也就是说,View没有正确绑定到模型。我知道你想要对所有桌子行进行一次操作。因此,我深刻建议您阅读Model Containing List of Models (MVC-3, Razor)问题并相信您的问题将得到解决。

如果您想知道enctype = "multipart/form-data"是什么,请阅读What does enctype='multipart/form-data' mean?

问候。

答案 2 :(得分:0)

这适用于MVC 5

  1. 在构造函数中创建实例可确保您不会获得null
  2. 明确地绑定列表,这样您就可以从视图中获得答案

    [Bind(Include = "UserList")]
    public class AdminViewModel
    {
        public AdminViewModel()
        {
            this.UserList = new List<User>();
        }
    
        public List<User> UserList { get; set; }
    }