0

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");
    }
1
  • Show your model and the method your posting to. This is not the way to generate a checkbox (and is your id property really a boolean?) Commented Oct 15, 2016 at 8:52

2 Answers 2

5

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);
Sign up to request clarification or add additional context in comments.

Comments

-1

I had the same problem. What worked for me was taking off the value="xxx" tag. Then it functioned normally. (Weird, I know.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.