4

I'm a bit confused by the behavior of ASP.NET MVC with it not changing the value of a dropdown list after a POST. Can someone explain how to do this.

First of all I have a model that looks like this:

public class Test
{
    public int OneID { get; set; }
    public IEnumerable<SelectListItem> OneList
    {
        get
        {
            yield return new SelectListItem
            {
                Text = "Red",
                Value = "0"
            };
            yield return new SelectListItem
            {
                Text = "Green",
                Value = "1"
            };
            yield return new SelectListItem
            {
                Text = "Blue",
                Value = "2"
            };
        }
    }

    public int TwoID { get; set; }
    public IEnumerable<SelectListItem> TwoList
    {
        get
        {
            yield return new SelectListItem
            {
                Text = "Ruby",
                Value = "0"
            };
            yield return new SelectListItem
            {
                Text = "Gem",
                Value = "1"
            };
            yield return new SelectListItem
            {
                Text = "Bronze",
                Value = "2"
            };
        }
    }
}

The view has this snippet of code in the body content:

<% using (Html.BeginForm("Index", "Home", FormMethod.Post))
   { %>
<table>
    <tr>
        <td>
            <% =Html.DropDownList("OneID", Model.OneList, new 
                  { @onchange = "this.form.submit();" })%>
        </td>
        <td>
            <% =Html.DropDownList("TwoID", Model.TwoList)%>
        </td>
    </tr>
</table>
<% } %>

And the GET and POST actions look like this:

public ActionResult Index()
{
    Test test = new Test();
    test.OneID = 0;
    test.TwoID = 0;
    return View(test);
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Test test)
{
    test.TwoID = test.OneID;
    return View(test);
}

What I'm trying to achieve is to change the selected item in the second drop down to match the first drop down each time the first drop down is changed. So I'm getting the selected value from the first drop down and assigning it to the ID used for the second drop down and then returning the same model. The first drop down is correctly set in the view but not the second one.

Ideas?

Guy
  • 65,082
  • 97
  • 254
  • 325

1 Answers1

1

The reason this doesn't work the way you expect it is because when the DropDownList helper tries to render the select element it first looks for posted values that match the name which in this case is TwoID and use this value instead of the value in the model. This is the same with a TextBox for example. If you use this helper and in the POST controller action you modify the value of the model it will still show the old value. That's just how helpers work. They bind from POSTed values.

There are two possible workarounds:

  1. Use javascript to synchronize both dropdowns:

    @onchange = "document.getElementById('TwoID').value = this.value; this.form.submit();"
    

    BTW this should be done in an unobtrusive way in a separate javascript file:

    $(function() {
        $('#OneID').change(function() {
            $('#TwoID').val($(this).val());
            this.form.submit();
        });
    });
    
  2. Write your own helper or generate the select manually (less recommended)

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks for the answer Darin. My example is contrived to distill the essence on the problem. The actual application I'm working on is complex and although I could do it in JavaScript it would require a lot more coding - however, this may be the only solution. Question: Is there anyway to destroy or change the POST'd values before the view engine uses them? I tried modifying the Request.Form["TwoID"] value but as I suspected it's read only. If I could blat all the POST'd values would the helper's then read from the model as a fall back? – Guy Feb 07 '10 at 16:51