3

I'm using CheckboxFor when building a form which has a list of checkboxes:

                            <div id="TestSections">
                            @foreach (var item in Model)
                            {
                                <div class="form-group">
                                    <label class="col-md-2 control-label">
                                        @if (item.IsRequried)
                                        {
                                            <text>Required - </text>
                                        }
                                        @item.Name
                                    </label>
                                    <div class="md-checkbox-list col-md-10">
                                        <div>
                                            @Html.CheckBoxFor(i => item.IsChecked)
                                        </div>
                                    </div>
                                </div>
                            }
                        </div>

The Model being passed is:

    public class TestModel
{
    public int TestId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public bool IsRequired { get; set; }
    // used for checkbox
    public bool IsChecked { get; set; }
}

The view builds out the checkboxes correct, but i'm not able to get them when the form posts back:

        [HttpPost]
    public ActionResult TestSection(int id, List<TestModel> model)
    {
        return View();
    }

the model is always null.

Paritosh
  • 4,243
  • 7
  • 47
  • 80
  • Suggest you also review [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943) for an explanation of why using a `foreach` loop will not work –  Apr 26 '16 at 22:50

3 Answers3

3

It is because you are using foreach for List model. Try rewrite it as follows:

for(int i=0;i<Model.Count;++i)
{
    @Html.CheckBoxFor(model => model[i].IsChecked)
}
zabulus
  • 2,373
  • 3
  • 15
  • 27
  • 1
    And what difference is this going to make? – Jamie Rees Apr 26 '16 at 14:16
  • MVC can't bind OP's model. If use indexer, everything is fine. And before downvote you could try run provided code and see what Fiddler shows. – zabulus Apr 26 '16 at 14:17
  • @JamieR This is how it is done if you have a list of checkboxes that need to retain their values when posting. Try out the code and see for yourself. Indexes are the only way to solve this. – Brendan Vogt Apr 26 '16 at 14:32
3

I had a similar issue a while back back. The way of displaying items from your list is a bit different than what you would normally do. You are going to have a for loop now and access each item in your list with an index variable. Indexes are needed so that you can keep track as to which checkbox was set to true and which is false.

In your view you could have the following code:

@model List<TestModel>

@using (Html.BeginForm())
{
     @for (int i = 0; i < Model.Count; i++)
     {
          <div>@Html.CheckBoxFor(m => m[i].IsChecked)</div>
     }
}

I tried to change it like yours, haven't tested it though:

<div id="TestSections">
     @for (int i = 0; i < Model.Count; i++)
     {
          <div class="form-group">
               <label class="col-md-2 control-label">
                    @if (item.IsRequried)
                    {
                         <text>Required - </text>
                    }
                    @item.Name
               </label>
               <div class="md-checkbox-list col-md-10">
                    <div>
                         @Html.CheckBoxFor(i => i[i].IsChecked)
                    </div>
               </div>
          </div>
     }
</div>

In your controller your action methods will look something like this:

public ActionResult TestSection(int id)
{
     List<TestModel> models = new List<TestModel>();
     // Populate your list and send it to the view

     return View(models);
}

[HttpPost]
public ActionResult TestSection(int id, List<TestModel> model)
{
     // Do what ever you need to do
     return View();
}

I hope this helps.

Brendan Vogt
  • 25,678
  • 37
  • 146
  • 234
  • The `item` will not exist, still need adjustment for OP. Btw, I wonder if the OP's code will run, he is using `IsRequried` in the view, while it's `IsRequired` in the model. – stenlytw Apr 26 '16 at 14:43
0

model list binding if you are working with list

   int i =0;
    @foreach (var item in Model)
    {
        @Html.CheckBox("myModel["+i+"].IsChecked",item.IsChecked)
        i++;
    }
Imran Luhur
  • 447
  • 3
  • 15