Dowemo
0 0 0 0


Question:

I have two checkboxes in my MVC app which are both boolean / bit fields. "NotifyEmail" & "NotifySMS".

Whenever I post back to the server and an error occurs, the state of the checkbox is gone event though I set attempted values.


Best Answer:


Update:This is fixed in RC2.

This question together with this one,

Html.Checkbox does not preserve its state in ASP.net MVC,

addresses a very undocumented feature of the ASPNET.MVC RC1. I have been searching around for hours to find a good answer, but there are very few to find.

There is a bug, apparently, which prohibit checkboxes and radiobuttons to maintain their state from ModelState. As we also know by now, is that these two controls are handled specially by the Html helpers.

The best I managed to come up with, was to build my own ViewBinder:

From a very simple view:

<h2>Keep checkbox value between posts</h2>
<% using (Html.BeginForm("update", "checkbox")) {%>
<p><%= Html.CheckBox("a") %></p>
<p><%= Html.CheckBox("b") %></p>
<p><%= Html.TextBox("dummy") %></p>
<input type="submit" value="update" />
<% } %>

Associated with an equally simple controller:

public class CheckboxController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    public ActionResult Update()
    {
        var binder = new ViewBinder(ViewData, ValueProvider);
        binder.UpdateBooleanValues("a", "b");
        binder.UpdateMissingValues();
        return View("Index");
    }
}

And a simple class to make it all work:

internal class ViewBinder
{
    private readonly IDictionary<string, ValueProviderResult> valueProvider;
    private readonly ViewDataDictionary viewData;
    public ViewBinder(ViewDataDictionary viewData, IDictionary<string, ValueProviderResult> valueProvider)
    {
        this.valueProvider = valueProvider;
        this.viewData = viewData;
    }
    public void UpdateMissingValues()
    {
        foreach (var key in valueProvider.Keys)
        {
            if (ValueIsMissing(key)) UpdateValue(key);
        }
    }
    public void UpdateBooleanValues(params string[] names)
    {
        foreach (var name in names)
        {
            UpdateValue(name, BooleanValueFor(name));
        }
    }
    private bool BooleanValueFor(string name)
    {
        return valueProvider[name].AttemptedValue != "false";
    }
    private bool ValueIsMissing(string key)
    {
        return viewData.ContainsKey(key) == false;
    }
    private void UpdateValue(string key)
    {
        var value = valueProvider[key].AttemptedValue;
        UpdateValue(key, value);
    }
    private void UpdateValue(string key, object value)
    {
        viewData[key] = value;
    }
}



Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs