I noticed what seems to me a bug in asp.net MVC or simply I am doing something wrong. I am currently using 1.0 so maybe this is something that will be addressed in the 2.0 release. But either way, here we go.
When I my view model has a property which is the same name as the declared id for a drop down list, the selected item is ignored and the rendered html has nothing selected. Not sure if I did something wrong, but changing the name of the id fixes the problem. I simplified the example, hope it is clear, otherwise please let me know.
Here is my view where the declared ID is the same name as my list in the model:
<table border="0" cellpadding="0" cellspacing="0"> <tr> <td> <%= Html.DropDownList("IsMultipleServicers", Model.IsMultipleServicers) %> </td> </tr> </table>
And the rendered Html
<table border="0" cellpadding="0" cellspacing="0"> <tr> <td> <select id="IsMultipleServicers" name="IsMultipleServicers"> <option value="false">No</option> <option value="true">Yes</option> </select> </td> </tr> </table>
Now lets make a small change. I will change the declared id to be something different.
Here is my View:
<table border="0" cellpadding="0" cellspacing="0"> <tr> <td> <%= Html.DropDownList("MultipleServicers", Model.IsMultipleServicers) %> </td> </tr> </table>
And now the rendered html:
<table border="0" cellpadding="0" cellspacing="0"> <tr> <td> <select id="IsMultipleServicers" name="IsMultipleServicers"> <option value="false">No</option> <option selected="selected" value="true">Yes</option> </select> </td> </tr> </table>
Notice that now I get a selected option which would be the second element in the List.
Here is my ViewModel just to tie everything together:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace MVCProject.Models.ViewModels.Service { public class ServiceViewModel : ViewModel { public List<SelectListItem> IsMultipleServicers { get; set; } } }
Here is my action:
[AcceptVerbs(HttpVerbs.Get)] public virtual ActionResult Service() { return View(new ServiceViewModel() { IsMultipleServicers = BuildBooleanSelectList(true) }; } private List<SelectListItem> BuildBooleanSelectList(bool isTrue) { List<SelectListItem> list = new List<SelectListItem>(); if (isTrue) { list.Add(new SelectListItem() { Selected = false, Text = "No", Value = "false" }); list.Add(new SelectListItem() { Selected = true, Text = "Yes", Value = "true" }); } else { list.Add(new SelectListItem() { Selected = true, Text = "No", Value = "false" }); list.Add(new SelectListItem() { Selected = false, Text = "Yes", Value = "true" }); } return list; }
You can set the SelectedValue to the value you want to select. If you already have selected item then you should clear the selection otherwise you would get "Cannot have multiple items selected in a DropDownList" error. dropdownlist. ClearSelection(); dropdownlist.
I think the problem is a confusion regarding the DropDownList
overloads:
Html.DropDownList(string name)
looks for a view model property of name
and type IEnumerable<SelectListItem>
. It will use the selected item (SelectListItem.Selected == true
) from the list, unless there is a form post value of the same name.
Html.DropDownList(string name, IEnumerable<SelectListItem> selectList)
uses the items from selectList
, but not their selected values. The selected is found by resolving name
in the view model (or post data) and matching it against the SelectListItem.Value
. Even if the value cannot be found (or is null), it still won't use the selected value from the list of SelectListItems.
Your code uses the second overload, but specifies a "value" property that doesn't exist ("MultipleServicers").
To fix your problem, either use the first overload:
<%= Html.DropDownList("IsMultipleServicers") %>
Or, add a string MultipleServicers
property to your view model and populate it in your controller. I'd recommend this solution as it gets around several problems with initial display, post display and mapping the post data to a view/post model:
public class ServiceViewModel : ViewModel { public string MultipleServicers { get; set; } public List<SelectListItem> IsMultipleServicers { get; set; } }
Then for your HTML:
<%= Html.DropDownList(Model.MultipleServicers, Model.IsMultipleServicers) %>
This technique maps into MVC2, as well:
<%= Html.DropDownListFor(x => x.MultipleServicers, Model.IsMultipleServicers) %>
I encountered this same problem using the Html.DropDownList(string name, IEnumerable selectList) overload. It appears that my model has a property of the same name as the name of the drop down list. This being the case, MVC favored the property value of my Model over the Selected property of each entry in the IEnumerable.
The solution was to use a name for the dropdown list that does not match up to a property name. Another solution would be to write my own extension method that ignores model and view state and instead always honor the selected property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With