G_Man
G_Man

Reputation: 1343

Working with checkboxes in asp.net mvc3 plus mass update

Currently I am attempting to create a mass update based on a series of checkboxes. I can't seem to find the correct way to do it using the entity framework.

I am using ASP.Net 4 with MVC3 and Razor.

Here is the code I have so far.

View Page (Working Properly)

@model List<LeagueCounters.Models.champion>
<form name="setFree id="setFree" method="POST" action="/Champion/SetFree">
    @foreach (var item in Model)
    {
        if (item.isFree == true)
        {
           <input type="checkbox" id="@item.id" checked="checked" /> @Html.DisplayFor(modelItem => item.displayName)  
        }
        else
        {
            <input type="checkbox" id="@item.id" /> @Html.DisplayFor(modelItem => item.displayName)
        }
    }
<p><input type="submit" value="Save" /></p>

Controller (Errors)

[HttpPost, Authorize(Roles = "Admin")]
public ActionResult SetFree(FormCollection fcMain)
{
     var sortedList = from c in _db.champions
                      orderby c.name
                      select c;
     int counter = 0;
     foreach (champion champ in sortedList)
     {
         if (fcMain[counter].Contains("true"))
            champ.isFree = true;
         else
            champ.isFree = false;

         _db.champions.Attach(champ);
         _db.ObjectStateManager.ChangeObjectState(champ, EntityState.Modified);

         counter++;
     }

     _db.SaveChanges();

     return View();
}

Errors

Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index

Question

How do I properly cycle through the checkboxes in the controller? And will my mass update code work once I get to that point?

Thanks in Advance.

Upvotes: 3

Views: 498

Answers (2)

Parv Sharma
Parv Sharma

Reputation: 12705

i think this line

fcMain[counter].Contains("true")

is causing the errors..are you using some kind of constraint selection(Where) when providing the model to the View

also you should add a hidden field after every checkbox by doing

<input type="hidden" value="false" id="@item.id" name="@item.id"/>

this way all the checkboxes will be submitted successfully
and you will have to split the values and take the first value thats present on the server side.
or you can skip both and directly use @Html.Checkbox(item.Id,item.isFree) this way the code will be cleaner and no need to manually add additional Hidden Input will be added automatically by the Razor engine

there are also some other improvements you can do to keep code DRY.
change this

if (item.isFree == true)
{
   <input type="checkbox" id="@item.id"  checked="checked" /> @Html.DisplayFor(modelItem => item.displayName)  
}
else
{
   <input type="checkbox" id="@item.id" /> @Html.DisplayFor(modelItem => item.displayName)
}

to

<input type="checkbox" id="@item.id" name="@item.id" @(!Item.isFree?"checked=\"checked\":\"\"") /> @Html.DisplayFor(modelItem => item.displayName)

and i dont think you need these

_db.champions.Attach(champ);
_db.ObjectStateManager.ChangeObjectState(champ, EntityState.Modified);

Upvotes: 0

Muhammad Adeel Zahid
Muhammad Adeel Zahid

Reputation: 17784

The problem here is that only the checked checkboxes are posted to the server. So you can't expect all of your checkbox keys to be present in the form collection. To workaround this behavior Html.CheckBoxFor creates an additional hidden field with checkbox so the result could be read on the server side. I am not sure how would you use strongly typed helper here because you are rendering data in a loop. I think you can have a look at this google search

Upvotes: 2

Related Questions