Reputation: 89
i have created a list of model binder with checkbox that is supposed to handle my forms but when i post to controller it always set checkbox to false even if it is checked on client side, any help?
my model
public class RoleCheckbox
{
public int id { get; set; }
public bool ischecked { get; set; }
public string name { get; set; }
}
public class UsersNew
{
public IList<RoleCheckbox> Roles { get; set; }
[Required,MaxLength(128)]
public string username { get; set; }
[Required,DataType(DataType.Password)]
public string password { get; set; }
[Required,MaxLength(256),DataType(DataType.EmailAddress)]
public string email { get; set; }
}
client code
<div class="panel panel-default">
<div class="panel-heading">Roles</div>
<div class="panel-body">
<ul class="list-group">
@for (var i = 0; i < Model.Roles.Count; i++)
{
<li class="list-group-item">
@Html.Hidden("Roles[" +i +"].id",Model.Roles[i].id)
<label for="Roles_@(i)_ischecked">
@Html.CheckBox("Roles[" +i+ "].id",Model.Roles[i].ischecked)
@Model.Roles[i].name
</label>
</li>
}
</ul>
</div>
</div>
my method
HttpPost,ValidateAntiForgeryToken]
public ActionResult New(UsersNew form)
{
var user = new User();
syncRole(form.Roles, user.Roles);
if (Database.Session.Query<User>().Any(u => u.username == form.username))
ModelState.AddModelError("username", "username must be unique");
if (!ModelState.IsValid)
return View(form);
user.email = form.email;
user.username = form.username;
user.SetPassword(form.password);
Database.Session.Save(user);
return RedirectToAction("index");
}
Upvotes: 0
Views: 5473
Reputation: 59
I had the same problem. What worked for me was taking off the value="xxx" tag. Then it functioned normally. (Weird, I know.)
Upvotes: -1
Reputation:
The @Html.CheckBox()
, and the preferred @Html.CheckBoxFor()
methods are for binding to bool
properties. They generate a checkbox input with a value of true and a hidden input with a value of false. You attempting to bind it to property id
and the value of true
or false
cannot be bound to an int
. In any case, you already have a hidden input for property id
, so the value of the checkbox is ignored (the DefaultModelBinder
only reads the first form value matching a property name).
The value of your ischecked
is always false
because you never submit any value for it so its just its default value
Always use the stronlgly typed ***For()
methods, and bind the checkbox to the bool
property. Your view should be
<ul class="list-group">
@for (var i = 0; i < Model.Roles.Count; i++)
{
<li class="list-group-item">
@Html.HiddenFor(m => m.Roles[i].id)
@Html.CheckBoxFor(m => m.Roles[i].ischecked)
@Html.LabelFor(m => m.Roles[i].ischecked, Model[i].name)
</li>
}
</ul>
Note that the name
property will not be submitted unless you also include @Html.HiddenFor(m => m.Roles[i].name)
In the POST method you can then get the ID's of the selected roles using
IEnumerable<int> selected = model.Roles.Where(x => x.ischecked).Select(x => x.id);
Upvotes: 5