Reputation: 1135
Here are my view models:
public class UserViewModel
{
public User GroupUser { get; set; }
public bool Checked { get; set; }
}
public class GroupUserViewModel
{
public Guid GroupId { get; set; }
public string GroupName { get; set; }
public IList<UserViewModel> Users;
}
My view:
@model GroupUserViewModel
@{
ViewBag.Title = "Users";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>@Model.GroupName</h2>
@using (Html.BeginForm("AddUserToGroup", "Group", FormMethod.Post))
{
for (var userIter = 0; userIter < Model.Users.Count(); userIter++)
{
<div class="form-group">
@Html.DisplayFor(model => model.Users[userIter].GroupUser.UserName)
@Html.CheckBoxFor(model => model.Users[userIter].Checked)
@Html.HiddenFor(model => model.GroupId)
@Html.HiddenFor(model => model.GroupName)
</div>
}
<input type="submit" class="btn btn-success" value="Save"/>
}
My controller:
[HttpPost]
public ActionResult AddUserToGroup(GroupUserViewModel groupUsers)
{
//do things
}
I had an inspection of the POST data and it is:
Users[0].Checked=true
Users[0].Checked=false
Users[1].Checked=false
For the boxes I've ticked there are 2 entries, one true
and one false
. Is this normal?
Also in the controller, what I get back is:
groupUsers.GroupId = {00000000-0000-0000-0000-000000000000}
groupUsers.GroupName = null
groupUsers.Users = null
Obviously since the form isn't actually posting the view model I want back to the controller, this happens. Is there any way to pass the required view model back to the controller since I need the GroupId
and GroupName
?
EDIT:
After some updates and adding in hidden fields for GroupId
and GroupName
, now the POST data is:
Users[0].Checked=true
Users[0].Checked=false
Id=015f5aef-eb6c-449e-9f08-9d42110c5347
GroupName=MyName
MyObjects[1].Checked=false
Id=015f5aef-eb6c-449e-9f08-9d42110c5347
GroupName=MyName
The GroupId
and GroupName
are now being passed corrently but the list is still null
.
Upvotes: 1
Views: 1581
Reputation:
IList<UserViewModel> Users
in GroupUserViewModel
is a field, not a property so the DefaultModelBinder
cannot set its value. Change it to
public class GroupUserViewModel
{
....
public IList<UserViewModel> Users { get; set; } // make it a property
}
Upvotes: 1
Reputation:
Yes this is normal. The reason is because an unchecked checkbox will not post a value, so ASP.NET renders a hidden field for every checkbox with the same ID as the checkbox just after the checkbox control, and sets its value to false. ASP.NET DefaultModelBinder will, if there are multiple form fields with the same name, take the first value. This results in one value of false being posted from the hidden field if the checkbox is not checked, and two values, one of false for the hidden field and one of true for the checked checkbox. Because the hidden field comes after the checkbox, if the checkbox posts a value, it will override the hidden field. However, that doesn't answer your question as to why the model isn't binding..
Upvotes: 4