Caution: This question is over nine years old!
Your best option is to search for newer questions, or to search the answers below looking for your specific version of MVC, as many answers here are obsolete now.
If you do find an answer that works for your version, please make sure the answer contains the version of MVC you are using.
(The original question starts below)
This seems a bit bizarre to me, but as far as I can tell, this is how you do it.
I have a collection of objects, and I want users to select one or more of them. This says to me "form with checkboxes." My objects don't have any concept of "selected" (they're rudimentary POCO's formed by deserializing a wcf call). So, I do the following:
public class SampleObject{
public Guid Id {get;set;}
public string Name {get;set;}
}
In the view:
<%
using (Html.BeginForm())
{
%>
<%foreach (var o in ViewData.Model) {%>
<%=Html.CheckBox(o.Id)%> <%= o.Name %>
<%}%>
<input type="submit" value="Submit" />
<%}%>
And, in the controller, this is the only way I can see to figure out what objects the user checked:
public ActionResult ThisLooksWeird(FormCollection result)
{
var winnars = from x in result.AllKeys
where result[x] != "false"
select x;
// yadda
}
Its freaky in the first place, and secondly, for those items the user checked, the FormCollection lists its value as "true false" rather than just true.
Obviously, I'm missing something. I think this is built with the idea in mind that the objects in the collection that are acted upon within the html form are updated using UpdateModel()
or through a ModelBinder.
But my objects aren't set up for this; does that mean that this is the only way? Is there another way to do it?
I'd also like to point out that you can name each checkbox a different name, and have that name part of the actionresults parameters.
Example,
View:
Controller:
The values from the view are passed to the action since the names are the same.
I know this solution isn't ideal for your project, but I thought I'd throw the idea out there.
From what I can gather, the model doesn't want to guess whether checked = true or false, I got around this by setting a value attribute on the checkbox element with jQuery before submitting the form like this:
This way, you don't need a hidden element just to store the value of the checkbox.
Html.CheckBox is doing something weird - if you view source on the resulting page, you'll see there's an
<input type="hidden" />
being generated alongside each checkbox, which explains the "true false" values you're seeing for each form element.Try this, which definitely works on ASP.NET MVC Beta because I've just tried it.
Put this in the view instead of using Html.CheckBox():
Your checkboxes are all called
selectedObjects
, and thevalue
of each checkbox is the GUID of the corresponding object.Then post to the following controller action (or something similar that does something useful instead of Response.Write())
This example will just write the GUIDs of the boxes you checked; ASP.NET MVC maps the GUID values of the selected checkboxes into the
Guid[] selectedObjects
parameter for you, and even parses the strings from the Request.Form collection into instantied GUID objects, which I think is rather nice.Same as nautic20's answer, just simply use MVC default model binding checkbox list with same name as a collection property of string/int/enum in ViewModel. That is it.
But one issue need to point out. In each checkbox component, you should not put "Id" in it which will affect MVC model binding.
Following code will work for model binding:
Following codes will not binding to model (difference here is it assigned id for each checkbox)
I'm surprised none of these answers used the built in MVC features for this.
I wrote a blog post about this here, which even actually links the labels to the checkbox. I used the EditorTemplate folder to accomplish this in a clean and modular way.
You will simply end up with a new file in the EditorTemplate folder that looks like this:
in your actual view, there will be no need to loop this, simply 1 line of code:
Visit my blog post for more details.
They appear to be opting to read the first value only, so this is "true" when the checkbox is checked, and "false" when only the hidden value is included. This is easily fetched with code like this: