views:

605

answers:

2

In ASP.NET MVC a checkbox is generated by the HtmlHelper code here:

<%= Html.CheckBox("List_" + mailingList.Key, true) %>

as this HTML:

<input id="List_NEW_PRODUCTS" name="List_NEW_PRODUCTS" type="checkbox" value="true" />
<input name="List_NEW_PRODUCTS" type="hidden" value="false" />

In case you're wondering why is there an extra hidden field? - then read this. Its definitely a solution that makes you first think 'hmmmmm' but then you realize its a pretty elegant one.

The problem I have is when I'm trying to parse the data on the backend. Well its not so much of a problem as a concern if anything in future were to change in the framework.

If I'm using the built in binding everything is great - its all done for me. But in my case I'm dynamically generating checkboxes with unknown names and no corresponding properties in my model.

So i end up having to write code like this :

if (forms["List_RETAIL_NOTIFICATION"] == "true,false") {

}

or this:

if (forms.GetValues("List_RETAIL_NOTIFICATION")[0] == "true") {

}

Both of which i still look at and cringe - especially since theres no guarantee this will always be the return value. I'm wondering if theres a way to access the layer of abstraction used by the model binders - or if I'm stuck with my controller 'knowing' this much about HTTP POST hacks.

Yes I'm maybe being a little picky - but perhaps theres a better clever way using the model binders that I can employ to read dynamically created checkbox parameters.

In addition i was hoping this this post might help others searcheing for : "true,false". Even though I knew why it does this I just forgot and it took me a little while to realize 'duh'.


FYI: I tried another few things, and this is what I found :

forms["List_RETAIL_NOTIFICATION"] evaluates to "true,false" forms.GetValues("List_RETAIL_NOTIFICATION")[0] evaluates to "true" (forms.GetValue("List_RETAIL_NOTIFICATION").RawValue as string[])[0] evaluates to "true" forms.GetValues("List_RETAIL_NOTIFICATION").FirstOrDefault() evaluates to "true"

A: 

If you:

  1. Create a model with a list or something for the "custom" property values
  2. Inherent from DefaultModelBinder
  3. Override BindProperty, and that the custom property values in some appropriate place, such as a list within the model type.

Then I think this does pretty much what you want. You're using the default binding for Boolean fields, but adding your own custom properties, without relying on reflection of your model type. See the release notes for the Release Candidate for more details on creating a custom model binder.

Craig Stuntz
A: 

The default model binder handles this fine. So if you have:

public ActionResult Save(bool List_RETAIL_NOTIFICATION)

or

public ActionResult Save(MyObjectWithABoolPropertyToBeBoundFromACheckBox myObject)

is should work fine.

Tim Scott
thanks, but like I said "I'm dynamically generating checkboxes with unknown names and no corresponding properties in my model". the checkboxes represent all the different mailing lists a user may sign up for - and this is database driven
Simon_Weaver
A good solution might be to give them corresponding properties in your model -- i.e., an enumerable that you would you populate from your data. In your view generate checkboxes by iterating over that enumerable and naming checkboxes with an indexer. DefaultModelBinder should handle that.
Tim Scott
When I say to name checkboxes with an indexer, I am talking about like this: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Tim Scott