The early previews of the MVC Toolkit contained a few helpers that are not available in the current MVC Beta and MVC Beta Futures.  On of the ones that was nixed was the CheckBoxList helper.  I was in need of this type of functionality lately and found myself out of luck.  I needed to add a dynamic list of checkboxes to a form, like the roles that a user could possible be a member of.  These roles could be added to or deleted from at any time.

I looked to the Html.CheckBox helper to see if that would work.  This helper can be used like so:

   1: /* The model for this is a Dictionary<string,bool> that contains 
   2:    the name for the role and whether the user is a member */
   3:  
   4: <% foreach (var info in ViewData.Model) { %>
   5:     <div><%= Html.CheckBox(info.Key, info.Value) %> <%= info.Key %></div>
   6: <% } %>

The problem with using Html.CheckBox for my scenario arises when you need to get the values in the form ActionMethod.  For Html.CheckBox, the form handler is expecting a boolean parameter for each checkbox.  An example is show below.

   1: [AcceptVerbs(HttpVerbs.Post)]
   2: public ActionResult Roles(bool administrator, bool user, bool poweruser)
   3: {
   4:     // Each bool parameter is the checked value for the checkbox that 
   5:     // has the same name.  If my list of roles is dynamic, this does
   6:     // not work so well :(
   7: }

As you can see, this would not satisfy the requirements that I had.  So what is the answer?  Create my own CheckBoxList helper of course.

Here is the extension method code for my implementation, along with a simple class that contains the info needed for each checkbox in the list..

   1: public static class InputExtensions
   2: {
   3:     public static string CheckBoxList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo)
   4:     {
   5:         return htmlHelper.CheckBoxList(name, listInfo,
   6:             ((IDictionary<string, object>) null));
   7:     }
   8:  
   9:     public static string CheckBoxList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
  10:         object htmlAttributes)
  11:     {
  12:         return htmlHelper.CheckBoxList(name, listInfo, 
  13:             ((IDictionary<string, object>)new RouteValueDictionary(htmlAttributes)));
  14:     }
  15:  
  16:     public static string CheckBoxList(this HtmlHelper htmlHelper, string name, List<CheckBoxListInfo> listInfo,
  17:         IDictionary<string, object> htmlAttributes)
  18:     {
  19:         if (String.IsNullOrEmpty(name))
  20:             throw new ArgumentException("The argument must have a value", "name");
  21:         if (listInfo == null)
  22:             throw new ArgumentNullException("listInfo");
  23:         if (listInfo.Count < 1)
  24:             throw new ArgumentException("The list must contain at least one value", "listInfo");
  25:  
  26:         StringBuilder sb = new StringBuilder();
  27:  
  28:         foreach (CheckBoxListInfo info in listInfo)
  29:         {
  30:             TagBuilder builder = new TagBuilder("input");
  31:             if (info.IsChecked) builder.MergeAttribute("checked", "checked");
  32:             builder.MergeAttributes<string, object>(htmlAttributes);
  33:             builder.MergeAttribute("type", "checkbox");
  34:             builder.MergeAttribute("value", info.Value);
  35:             builder.MergeAttribute("name", name);
  36:             builder.InnerHtml = info.DisplayText;
  37:             sb.Append(builder.ToString(TagRenderMode.Normal));
  38:             sb.Append("<br />");
  39:         }
  40:  
  41:         return sb.ToString();
  42:     }
  43: }
  44:  
  45: // This the information that is needed by each checkbox in the
  46: // CheckBoxList helper.
  47: public class CheckBoxListInfo
  48: {
  49:     public CheckBoxListInfo(string value, string displayText, bool isChecked)
  50:     {
  51:         this.Value = value;
  52:         this.DisplayText = displayText;
  53:         this.IsChecked = isChecked;
  54:     }
  55:  
  56:     public string Value { get; private set; }
  57:     public string DisplayText { get; private set; }
  58:     public bool IsChecked { get; private set; }
  59: }

This can then be used to render the list of checkboxes in a View as shown below:

   1: /* Where ViewData.Model is a List of CheckBoxListInfo objects that
   2:    provide the details for the checkboxes. */
   3:  
   4: <div><%= Html.CheckBoxList("roles", ViewData.Model) %></div>

And now, in the post ActionMethod, we can access the ones that have been checked like so:

   1: [AcceptVerbs(HttpVerbs.Post)]
   2: public ActionResult Roles(string[] roles)
   3: {
   4:     /* The 'roles' parameter contains the values from the 
   5:        checkboxes that were checked. */
   6: }

In addition to solving the issue that I was having, this post shows how easy it is to implement your own custom helpers in MVC.