Reputation: 1343
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.
@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>
[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();
}
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
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
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
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