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.
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
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);
Related
Here am pressing the pay button i have to pass ids and the form data
in my view am displaying some data using for each loop,and when i click a button i have to pass the number of ids which returns in model class and some form data(which is outside the model class) to the controller,i have tried my maximum,But i failed,please help me to make this?
view.cshtml
#foreach (var item in Model) {
<input type="hidden" value="#item.vid" name="abc" />//i need these ids in my controller
<tr>
<td>
<td> #Html.DisplayFor(modelItem => item.vid)</td>
.........
...........//some more displaying
}
#Html.BeginForm("makepayment","home",FormMethod.Post)
{
<h3>Card Holder Name</h3>
<input type="text" name="cname" />
<h3>Account Name</h3>
<input type="text" name="number" />
<h3>CVC</h3>
<input type="text" name="securitycode" />
<h3>Expiery Date</h3>
<input type="text" name="expdate" />
<input type="submit" id="sub" name="sub" value="pay" />
}
controller
public ActionResult makepayment(FormCollection values,????)
{
......
.......//codes
}
i know i may have to use array or something,but i dont know how,somebody please help
Now, following semantics, you should create a separate viewmodel class that can hold such information, but that is not always the case.
So here is my understanding. You have a model class which you are what your form consists of, but you also want to send the ids that are just related to something else. In you post action, you get an instance of your model class with model binding.
//Please ignore the [] chars
public ActionResult makepayment([Name of you model class] modelInstance)
{
//modelInstance will contain the fields of the model.
//The remaining field, you can access using.
//Request.Form["{name of the input field}"]
var id = Request.Form["abc"]
}
Hope this helps you out. Otherwise, hit me with up and we can easily go through it in more detail.
P.S :- I am not a sir.
I have a 'Survey' page which is declared as follows:
#using (Html.BeginForm("Survey", "Home", new { questionList = Model.Questions }, FormMethod.Post))
{
<div class="survey">
<ol class="questions">
#foreach (Question q in Model.Questions)
{
<li class="question" id="#q.QuestionName">
#q.QuestionText<br />
#foreach (Answer a in q.Answers)
{
<input class="answer" id="#a.DisplayName" type="checkbox" /><label for="#a.DisplayName">#a.AnswerText</label>
if (a.Expandable)
{
<input type="text" id="#a.DisplayNameFreeEntry" maxlength="250" /> <span>(250 characters max)</span>
}
<br />
}
</li>
}
</ol>
</div>
<div class="buttons">
<input type="submit" value="Finish" />
</div>
}
When I'm stepping through my code, it hits the method I've set up to process their survey:
[HttpPost]
public ActionResult Survey( List<Question> questionList, FormCollection postData)
{
//Process Survey
}
However, when I step through I am finding that the variable questionList is null and the variable postData does not contain any data from the Form. Trying to access checkboxes via Request[a.Displayname also does not work.
Everything I've read indicates that this is the correct way to persist values from the Model to the submission method, and that I should be able to access the FormCollection this way.
What am I doing wrong?
You have to save questionList as a hidden field on the page. Non-primitive types do not get persisted simply by passing them in.
One way you can do that is
#Html.HiddenFor(m => m.Foo)
Or you could do it directly in HTML like this
<input type="hidden" name="Var" value="foo">
where m is your model.
The fact that the postData is empty is weird, since every input element with id inside a form tag should be passed with the POST request.
But the questionList won't be received that way, since its a list of complex class (not just a string or int), and the default ModelBinder (the thing that turns the HTTP Request Variables into parameters passed to the action method) don't support lists of complex classes.
If you want to be able to receive List you will have to implement your own binding mechanism with CustomModelBinder.
This article can help you implement it.
One problem is your checkbox and your textbox are not properly bound to your model.
You should be using #Html.CheckBoxFor and #Html.TextBoxFor
I'm building an MVC app and right now my view generates a pack of items. The user needs to check a checkbox if he wants to send the data.
Here's my view and how it is builded:
<script type="text/javascript">
$(document).ready(function() {
//alert("The document is ready");
$("#selectAll").click(function() {
//alert("The case has been clicked");
var chkValue = $(this).is(":checked");
$(".divChckBox").prop("checked", chkValue);
});
});
</script>
<p>
#using (Html.BeginForm("SendObj", "Manager"))
{
<p>
Select / UnSelet All Items #Html.CheckBox("selectAll", true)
</p>
<table>
<tr>
<th>Card Name</th>
<th>Number In Stock</th>
(...)
</tr>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>#Html.DisplayFor(x => x[i].m_OthObj.m_ObjName)</td>
<td>#Html.DisplayFor(x => x[i].m_NbInStock)#Html.HiddenFor(x => x[i].m_NbInStock)</td>
(...)
<td>
<input type="checkbox" name="itdoesnotmatter" class="divChckBox" checked="true"/>
</td>
</tr>
}
</table>
<input type="submit" value="Send"/>
}
</p>
So you understand why I cannot use "CheckboxFor". Now what I want to do is send only the items which checkbox status is "checked". I know how to do this via model binding (checkboxfor), but I'm clueless as to how to build this.
I need to return a list of items. So how could I do this? Thank you very much!
Your form will return the values based on name, so shoot whoever told you such a stupid name :)
Use
<input type="checkbox" name="InStock" class="divChckBox" checked="true" value="#Model[i].ID" />
Or something more representative. Note that it is CRITICAL that you supply a unique identifier as the value of your checkbox. The value is how you will identify what was checked!
In your controller, there's several ways you can capture it. I do it like this:
public ActionResult Create(List<int> InStock)
{
foreach(var inStockItem in InStock)
{
//do what you need to do
}
}
The important points:
List<int> InStock
This must match the NAME attribute on your checkbox. The actual values will be the Value of your checkboxes.
Here I just randomly selected Create for your Action, but you need to make it match whatever action you are in (Edit, Index, etc..)
Good Luck!
try using the attr method to change the property checked.
$(document).ready(function() {
$("#selectAll").click(function() {
var chkValue = $(this).is(":checked");
$(".divChckBox").attr("checked", chkValue);
});
});
View code:
<!-- note "x[i].m_id"; Use the entity's id property is here
...maybe this should be m_NbInStock? -->
<input type="checkbox" name="selectedItems" value="#x[i].m_id" class="divChckBox" checked="true"/>
Controller code:
public class Manager : Controller
{
/* ... */
[HttpPost]
public ActionResult SendObj(IList<Int32> selectedItems)
{
// Grab those items by their IDs found within `selectedItems` and perform
// any processing necessary
// ...
//return View();
}
/* ... */
}
I have asp.net mvc 3 application. I have build the EDIT View which consist of different checkbox with same name and different value. I want to checked the checkbox by matching value of checkbox with the value in array of the string of c#.
Action:
public ActionResult Edit(int id)
{
string[] AllRole = roleassign.Role.Split(',');
ViewBag.allrole = AllRole;
ViewBag.role = ivr.get_all_role();
return View();
}
AllRole is array String consist of "administrator","member","supervisor"
View
#foreach (var list in ViewBag.role)
{
<input type="checkbox" name="role" value=#list.Name /> #list.Name
}
How Can I loop through the ViewBag.allrole array string in jquery and checked the checked box which have value that is in the ViewBag.allrole array string.
Edited
In View It Creates Entire set of Checkbox of all avaiable Role as follows:
<input type="checkbox" value="Administrator" name="role">
Administrator
<input type="checkbox" value="Moderator" name="role">
Moderator
<input type="checkbox" value="voice" name="role">
voiceanchor
<input type="checkbox" value="member" name="role">
member
If the ViewBag.allrole consist of array of "administrator","moderator" then I want to checked the checkbox with those value in checkbox using jquery
If you are using .NET Membership, you can do something like:
#foreach (var role in Roles.GetAllRoles)
{
bool checked = Roles.IsUserInRole(role);
<input
type="checkbox"
name="role"
value="#role.Name"
#(checked ? "checked='checked'" : "")/> #role.Name
}
in your particular example, you can do almost the same
string[] userRoles = ViewBag.role;
#foreach (var list in ViewBag.allrole)
{
bool checked = userRoles.Contains(role);
<input
type="checkbox"
name="role"
value="#list.Name"
#(checked ? "checked='checked'" : "")/> #list.Name
}
please change your variables accordingly if I missed something, as they're not very intuitive.
I have a view-model "MyClass" that contains a dictionary:
Dictionary<string, bool> columns {get; set;}
and it has keys and values
columns.Add("Name", true);
columns.Add("Type", true);
now, I want to let the user edit MyClass and its dictionary.
For every key I want to show its key and to enable to check\unchek its value (true\false), such that the input's name will be the right name for editing. since the dictionary has many keys, I need to to it with "foreach" or "for".
How can I do that?
You can start from http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-1
You need to write something like this in your View
#using (Html.BeginForm()) {
<fieldset>
<legend>MyClassViewModel</legend>
#foreach (var item in Model.Columns){
#Html.Label(item.Key)
#Html.CheckBox(item.Key, item.Value)
}
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
and your view must be bind to model in that case
#model MvcDemoApp.Models.MyClassViewModel
or as an alternative
#foreach (var item in Model.Columns)
{
#item.Key
<input type="checkbox" id="#item.Key" checked="#item.Value" />
<input type="hidden" value="#item.Value" />
<br />
}
or try using CheckBoxList custom helper by community
http://weblogs.asp.net/gunnarpeipman/archive/2011/05/05/asp-net-mvc-implementing-checkboxlist.aspx
http://www.codeproject.com/Articles/292050/MVC3-Html-CheckBoxList-custom-extension
In your case you want something like this, for the default binder to understand the name="" format:
<input type="checkbox" name="columns[0].Value" value="Key0 string value" />
<input type="checkbox" name="columns[1].Value" value="Key1 string value" />
Unfortunately the default helpers don't fully support this so you've to write the name="" explicitly. Something like:
#Html.CheckBox("columns[" + i + "].Value", new { value = columns[i].Key });
Read more about these kind of bindings on this blog post.