top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

Problem Setting The Default Value For ASP.NET MVC DropDownList

+5 votes
291 views

Recently one of the readers reported a problem that the DropDownList helper is not working as expected. The problem was resolved by slightly tweaking the code but since it sounded like a tricky thing that many beginners would stumble upon I am writing this post. Let's see what the problem is, its cause and finally the little tweak that I mentioned earlier.

Suppose that you have a View to enter Customer details such as CustomerID, CompanyName, ContactName and Country. The Country value is to be presented to the user as a DropDownList so that he can pick one value from the list. When the view is displayed the first time some default Country value must be selected in the DropDownList. This default value is not same as the first entry from the DropDownList. It is determined based on some condition (say language setting or some value saved in the database) and is to be assigned through code.

To accomplish this task the developer wrote this code:

public ActionResult New()
{
    var countryQuery = (from c in db.Customers
                        orderby c.Country ascending
                        select c.Country).Distinct();
    List<SelectListItem> countryList = new List<SelectListItem>();
    string defaultCountry = "USA";
    foreach(var item in countryQuery)
    {
        countryList.Add(new SelectListItem() {
                        Text = item, 
                        Value = item, 
                        Selected=(item == defaultCountry ? true : false) });
    }
    ViewBag.Country = countryList;
    return View();       
}

The above code shows New() action method of a controller. The code shown above selects distinct countries from the Customers table (Northwind database). It then declares a generic List of SelectListItem objects. A SelectListItem class represents one entry of the DropDownList. A foreach loop iterates through the available countries and adds the corresponding SelectListItem objects to the List. The Text and Value properties of the SelectListItem indicate the text of an item and the value of an item respectively. The Selected boolean property controls whether an item should be selected or not. The Selected property is set by checking the current country with the one stored in defaultCountry variable (USA in this case). Once a List of SelectListItem is created the List is passed to the view in a ViewBag property - Country.

The New view displayed by the New() action method is shown below:

@model DropDownListDemo.Models.Customer

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Edit</title>
</head>
<body>
    @using(Html.BeginForm("Insert","Home",FormMethod.Post))
    {
        @Html.TextBox("CustomerID")
        @Html.TextBox("CompanyName")
        @Html.TextBox("ContactName")
        @Html.DropDownList("Country", ViewBag.Country as List<SelectListItem>)
        <input type="submit" value="Insert" />
    }
</body>
</html>

The New view is quite straightforward and uses HTML helpers such as TextBox and DropDownList to render the respective form fields. The form is submitted to the Insert() action method of the Home controller. Notice the DropDownList markup. The DropDownList markup renders a <select> element with name equal to Country and Country ViewBag property supplies the List of SelectListItem objects to it.

So far so good. At this point you might expect that running the New view will render a DropDownList with USA selected in it. Right? Unfortunately, the answer is No. The DropDownList doesn't select USA at all. Instead the first item from the DropDownList gets selected.

What's the problem? The problem is the ViewBag property you created to pass the List to the view. If you observe the above code carefully, you will realize that the ViewBag property name and DropDownList name both are set to Country. This creates the problem. While rendering the DropDownList, MVC looks for a ViewData (and hence ViewBag) variable whose name is same as the DropDownLIst being rendered. If such a ViewData variable is found, value of that variable is used to determine the selected value of the DropDownList. If no compatible value is found nothing is set as the default. So, in the above code MVC is trying to assign the value of Country ViewBag property to Country DropDownList and they don't match. That's why USA is not selected in the DropDownList in spite of setting it as a default for one of the SelectListItem.

To rectify the problem simply change the name of the ViewBag property to something different. For example, the following code sets it to Countries instead of Country.

 public ActionResult New()
{
    ...
    ViewBag.Countries = countryList;
    return View();       
}

Also change the view markup as follows:

 @Html.DropDownList("Country", ViewBag.Countries as List<SelectListItem>)

If you run the view again, you will find that this time USA gets selected in the DropDownList. Just to confirm what I explained earlier add another ViewBag property as follows:

public ActionResult New()
{
    ...
    ViewBag.Countries = countryList;
    ViewBag.Country = "UK";
    return View();       
}

As you can see, two ViewBag properties are set - Countries and Country. The Countries property points to the List of SelectListItem objects whereas Country property holds a value of UK. If you run the view you will find that the DropDownList displays UK as its default value. Thus default of USA is overridden by ViewBag property with the same name as that of the DropDownList.

To summarize, whenever you wish to pass data for a DropDownList through ViewData or ViewBag, ensure that ViewData / ViewBag property names don't conflict with the form field names. In most of the cases you will need to change the ViewBag property names to something different because form field names are necessary for model binding to work correctly.

posted Oct 20, 2016 by Shivaranjini

  Promote This Article
Facebook Share Button Twitter Share Button LinkedIn Share Button

...