Andriy Tkach
Andriy Tkach

Reputation: 1471

MVC Html.CheckBox and form submit issue

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?

Upvotes: 14

Views: 42960

Answers (4)

Lord of Scripts
Lord of Scripts

Reputation: 3599

I use this:

public struct EditedCheckboxValue
{
    public bool Current { get; private set; }

    public bool Previous { get; private set; }

    public bool Changed { get; private set; }

    public EditedCheckboxValue(System.Web.Mvc.FormCollection collection, string checkboxID) : this()
    {
        string[] values = collection[checkboxID].Split(new char[] { ',' });
        if (values.Length == 2)
        {   // checkbox value changed, Format: current,old
            Current = bool.Parse(values[0]);
            Previous = bool.Parse(values[1]);
            Changed = (Current != Previous);
        }
        else if (values.Length == 1)
        {
            Current = bool.Parse(values[0]);
            Previous = Current;
            Changed = false;
        }
        else
            throw new FormatException("invalid format for edited checkbox value in FormCollection");
    }
}

and then call it like this:

EditedCheckboxValue issomething = new EditedCheckboxValue(collection, "FieldName");
instance.IsSomething = issomething.Current;

Upvotes: 0

TStamper
TStamper

Reputation: 30354

   <% 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"

Upvotes: 16

Andriy Tkach
Andriy Tkach

Reputation: 1471

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!

Upvotes: 2

veggerby
veggerby

Reputation: 9020

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

Upvotes: 10

Related Questions