我有一个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");
}
答案 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();
}
当你设置一个断点时,你可以看到你坚持模型如下 -
答案 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
明确地绑定列表,这样您就可以从视图中获得答案
[Bind(Include = "UserList")]
public class AdminViewModel
{
public AdminViewModel()
{
this.UserList = new List<User>();
}
public List<User> UserList { get; set; }
}