views:

7768

answers:

3

Crazy issue with submitting of values in Html.Checkbox in ASP.NET MVC RC

Some of the values are just not come to Request.Params

At my form I have this line inside the cycle:

<%=Html.CheckBox("cb" + p.Option.Id, p.Option.IsAllowed, new { value = 6 })%>

and it renders to next:

    <input checked="checked" id="cb17" name="cb17" type="checkbox" value="6" />
<input name="cb17" type="hidden" value="false" /> 

    <input checked="checked" id="cb18" name="cb18" type="checkbox" value="6" />
<input name="cb18" type="hidden" value="false" /> 

    <input id="cb19" name="cb19" type="checkbox" value="6" />
<input name="cb19" type="hidden" value="false" />

    <input id="cb20" name="cb20" type="checkbox" value="6" />
<input name="cb20" type="hidden" value="false" />

    <input checked="checked" id="cb21" name="cb21" type="checkbox" value="6" />
<input name="cb21" type="hidden" value="false" />

After submitting the Form I'm get something like:

Form.Params["cb17"] = {6, "false"}
Form.Params["cb18"] = {6, "false"}
Form.Params["cb19"] = {"false"}
Form.Params["cb20"] = {"6,false"}
Form.Params["cb21"] = {"false"}

In the request string Some of the params are displayed twice (normal situation) and some only ONE TIME (only value of hidden field). It seems that it doesn't rely on whether checkbox was checked or not, whether value has changed or so...

Does anybody faced with such a situation? How can I work around?

+3  A: 

This is actually the way it should work according to specifications.

It has nothing to do with ASP.NET MVC, but when a check box is left unchecked it is not included in the POST collection.

You get two values because you have both a checkbox and an input with the same name (and the ones you have two values for are most likely the ones with checkboxes checked).

Edit: specifications from W3C

veggerby
yes, now I see what is the rule explaining such behavior
Andrey Tkach
What? that is not true veggerby...In mvc the checkboxes are rendered differently then the normal html checkbox
TStamper
Yes, they are rendered as 2 inputs. But that doesn't change the fact that the check box are NOT part of the POST values unless checked which is what you get when you look at Form.Params[]. If you specify the bool as a param on your action, then yes it'll work as "expected". But that's MVC "magic".
veggerby
+6  A: 
   <% using(Html.BeginForm("Retrieve", "Home")) %>//Retrieve is the name of the action while Home is the name of the controller
       <% { %>
    <%foreach (var app in newApps)              { %>  
  <tr> 
       <td><%=Html.CheckBox(""+app.ApplicationId )%></td>      

   </tr>  
<%} %>
 <input type"submit"/>
<% } %>

and in your controller

 List<app>=newApps; //Database bind
 for(int i=0; i<app.Count;i++)
 {

    var checkbox=Request.Form[""+app[i].ApplicationId];
    if(checkbox!="false")// if not false then true,false is returned
 }

the reason you check for false because the Html Checkbox helper does some kind of freaky thing for value true

True returns as:

it makes the string read "true, false"

so you may have thought it was two values but its just one and means true

False returns as:

it makes the string read "false"
TStamper
Your solution is pretty well. But I'm thinking about Stateless form submitting. Regarding to Your example I don't know how much Objects do I have in app[i]
Andrey Tkach
I just updated. the app[i] was iterating through the form ids that was on the page.since the checkbox is dynamically bind, you must find the id in DB then compare each value from the form
TStamper
Is there a proper explanation on why this is the case? why "true, false" for true?
chakrit
@chakrit- Never found any documentation on it, just experienced it myself. I don't know why the implementation of html checkbox helpers render with the extra wierd behavior, hopefully it will be fixed in the future MVC releases, but I think its for doing something behind the scences
TStamper
It does make it easier in situations where you have a grid with Checkboxes and multiple pages to determine which ones have changed from true to false. This combined with the fact you might have the checkbox associated with an action parameter are two reasons I can think of for this implementation.
RichardOD
+2  A: 

Without the need to ask database about the ids after form submitting/before saving (Stateless mode) I've produced such code:

    foreach (string key in Request.Form)
    {
        var checkbox = String.Empty;
        if (key.StartsWith("cb"))
        {
          checkbox = Request.Form["" + key];

          if (checkbox != "false")
          {
              int id = Convert.ToInt32(key.Remove(0, 2));
          }
        }
    }

Thanks you guys to help me work around this issue!

Andrey Tkach