All input elements are equal, oh except checkboxes

A friend of mine has been doing some web design as a side job recently and came across something that also caught me out when I was new to HTML.  I'll start with a little background on the problem.

The input element comes in a number of different forms and is used for collecting data from users and then posting it to a server so that the server can do some work with it.  An example of this is the text input which allows you to enter text as you probably guessed.  An example for collecting a first name would look something like this.

<input type="text" name="firstname">

You'd then use some code server side to access the posted variable.  In php it would look something like this.


Now inputs come in a number of different forms depending on the value of the type attribute, another example that you will come across is radio buttons.  When you leave these input elements blank they normally will submit the field name with a blank value.  The more observant of you may have noticed I slipped in the word normally.  This pattern falls down when you start using checkboxes.  When a checkbox is left blank then neither the name nor the value is submitted.  Obviously this is not a problem if you know about this and expect it as you can simply check whether any value was submitted in php using the isset method.

if (isset($_POST['firstname'])) { }

This isn't so bad in php, however, at least a few of you I'm sure will be working with .NET and MVC specifically.  You may be wondering how the MVC model binding copes with checkboxes.  For those of you unfamiliar with MVC model binding it simply takes the posted values from your page and attempts to bind these to objects or parameters in a method.  Hopefully I'll go into this in a bit more detail in a few weeks as it's quite an interesting area but for the moment just know that if you have a method like this on an MVC controller

public ActionResult Index(string firstname) { }

and you have the text input element in the first example then MVC will magically map the text entered by the user to string firstname in the method signature.  It even works for complex objects but again that's another post.  Now I'm sure some of you may have realised that given that checkboxes aren't submitted if they are not checked this could cause problems for the MVC model binder.  The short answer is yes it could, however, the guys creating MVC know a bit about what they're doing so there is a trick that they use.  They've supplied a number of helper methods to help create html elements which is nice as it means we can create html elements like checkboxes without having to type the whole html block.  With the Razor engine in MVC you'd declare a checkbox like this with a default value of checked

@Html.CheckBox("CheckBoxName", true)

If you created a demo application, did this opened the page and looked at the html generated you'd see something like this.

<input checked="checked" id="CheckBoxName" name="CheckBoxName" type="checkbox" value="true">

You'd also see the following line.

<input name="CheckBoxName" type="hidden" value="false">

Now it's this line that is the trick they use, a second input element which is hidden to the user.  If you look look at the data posted by the form when the value is checked then you would see something like this.


When the checkbox is unchecked when the form is posted then you would see this.


This means that the MVC model binding always has a value to work from.  It also means that if you don't use the MVC helper methods to create your html then it can lead you into trouble if you rely on the defauly MVC model binding.  They gave us these helper methods for a reason!  Of course if you want to write cleaner HTML yourself by excluding the second hidden element then you can but you will have to write your own custom model binding.  Which thankfully the guys who wrote MVC made very easy to do.