POST到MVC控制器IEnumerable的嵌套型号为空时,我没有选择,为了复选框 [英] POST to MVC controller IEnumerable nested Model is null when I don't select checkboxes in order
问题描述
当我试图让值后的复选框的值设置为NULL的时候,我不以(1,2,3等),然后检查。
When I'm trying to get values in Post the values of checkboxes are set to NULL when I don't check then in order (1, 2, 3, etc).
我需要在没有为了选择其中任何(即4,5)。
I need to select any of them in no order (i.e. 4, 5).
MODEL:
public class AssignUsersViewModel
{
[Display(Name = "Check to select")]
public bool Select { get; set; }
public int Id { get; set; }
[Display(Name = "App. Username")]
public string UserName { get; set; }
[Required]
public string GivenName { get; set; }
[Required]
public string Surname { get; set; }
[Display(Name = "Roles")]
public IList<Roles> Roles { get; set; }
}
public class AssignUsersAddModel
{
public bool Select { get; set; }
public int Id { get; set; }
public IEnumerable<SelectedRoles> selectedRoles { get; set; }
}
public class SelectedRoles
{
public string Name { get; set; }
}
CSHTML:
CSHTML:
@model IList<AspNetIdentity2DRH.Models.AssignUsersViewModel>
@using (Html.BeginForm("UsersAddToApp", "UsersAdmin", FormMethod.Post))
{
@Html.AntiForgeryToken()
<table class="table">
<tr>
<th>Check for add</th>
<th>Username</th>
<th>Givenname</th>
<th>Surename</th>
<th>Roles</th>
</tr>
@for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
@Html.CheckBoxFor(x => x[i].Select)
@Html.HiddenFor(x => x[i].Id)
</td>
<td>
@Html.DisplayFor(x => x[i].UserName)
</td>
<td>
@Html.DisplayFor(x => x[i].GivenName)
</td>
<td>
@Html.DisplayFor(x => x[i].Surname)
</td>
<td>
<div class="row">
<div class="form-group">
@for (int j = 0; j < Model[i].Roles.Count(); j++)
{
<div class="col-sm-4">
<input type="checkbox" name="[@i.ToString()].selectedRoles[@j.ToString()].Name" value="@Model[i].Roles[j].Name" class="checkbox-inline" />
@Html.Label(Model[i].Roles[j].Name, new { @class = "control-label", @data_toggle = "tooltip", @data_placement = "top", @data_original_title = Model[i].Roles[j].Description })
</div>
}
</div>
</div>
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Add existing user" class="btn btn-primary" />
<input type="button" value="Cancel" onclick="window.location.href = '@Url.Action("UsersIndex", "UsersAdmin")';" class="btn btn-cancel" />
</p>
}
控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UsersAddToApp(List<AssignUsersAddModel> model)
{
if (ModelState.IsValid)
{
foreach (AssignUsersAddModel item in model)
{
if (item.Select)
{
using (DbContextTransaction dbtrans = db.Database.BeginTransaction())
{
try
{
int appId = (int)Session["ApplicationId"];
Users user = UserManager.FindById(item.Id);
db.ApplicationUsers.Add(new ApplicationUsers { ApplicationId = appId, UserId = user.Id });
db.SaveChanges();
foreach (SelectedRoles RolesItem in item.selectedRoles)
{
int roleId = db.Roles.Where(r => r.Name == RolesItem.Name).Select(r => r.Id).FirstOrDefault();
db.UserApplicationRoles.Add(new UserApplicationRoles { ApplicationId = appId, UserId = user.Id, RoleId = roleId });
db.SaveChanges();
}
dbtrans.Commit();
}
catch (Exception)
{
dbtrans.Rollback();
}
}
}
}
return RedirectToAction("UsersAddToApp");
}
ModelState.AddModelError("", "An error has occurred. Contact system administrator.");
return RedirectToAction("UsersAddToApp");
}
问题是,当我选择复选框(除了第一个,或最后o一个在中间,该行:
The problem is when I select checkboxes (all except the first, or the last o one in the middle, the line:
foreach (SelectedRoles RolesItem in item.selectedRoles)
发送item.selectedRoles为null。
Sends item.selectedRoles is null.
我怎么能做到这一点吗?
How I could do this right?
推荐答案
的 DefaultModelBinder
只会结合的集合,其中集合项的索引以零开始,是连续的。你的问题是你手动创建一个复选框元素。由于未选中复选框不回来后,如果你选中其中一个,那么它和任何后续复选框值当您提交将不会绑定到集合。
The DefaultModelBinder
will only bind collections where the indexers of the collection items start at zero and are consecutive. You problem is that you are manually creating a checkbox element. Since unchecked checkboxes do not post back, if you uncheck one, then it and any subsequent checkbox values will not be bound to the collection when you submit.
接下来你去一个复选框绑定到字符串
值。一个复选框有2个状态,旨在重新present一个布尔值。
Next your trying to bind a checkbox to a string
value. A checkbox has 2 states and is designed to represent a boolean value.
您还没有表现出你角色
(视图)模型,但它应该包括布尔
属性,来指示,如果有被选中
You have not shown you Role
(view) model but it should include a boolean
property indicating if it has been selected
public class Role
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
然后在视图中,使用强类型HTML辅助方法让你获得正确的双向模型绑定
Then in the view, use strongly type html helpers so you get correct 2 way model binding
@for (int j = 0; j < Model[i].Roles.Count; j++)
{
@Html.HiddenFor(m => m[i].Roles[j].Name) // or better use the ID property
@Html.CheckBoxFor(m => m[i].Roles[j].IsSelected)
@Html.LabelFor(m => m[i].Roles[j].IsSelected, Model[i].Roles[j].Name)
}
然后在POST方法,您的集合将被正确绑定,你可以使用访问选定的角色说,
Then in the POST method, your collection will be correctly bound and you could access the selected roles using say,
List<string> selectedRoles = model.Roles.Where(r => r.IsSelected);
请注意您可能还需要包括对 Role.ID
(而该 Role.Name
属性),所以你并不需要在您的文章的方法执行数据库查找的foreach
循环。
Note you may also want to include a hidden input for the Role.ID
(rather that the Role.Name
property) so you do not need to perform database lookups in your POST methods foreach
loop.
边注:您的帖子方法需要为
Side note: Your post method needs to be
public ActionResult UsersAddToApp(List<AssignUsersViewModel> model)
不是 ListAssignUsersAddModel&GT;模型
这篇关于POST到MVC控制器IEnumerable的嵌套型号为空时,我没有选择,为了复选框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!