11

I am having trouble getting my DropDownList to set the selected item to the value from the model.

The field in the model is just a string for the Title of the users name (Mr, Miss etc..) Below is my code so far.

<td>
@{ var list = new List<SelectListItem>(new[] {                    
    new SelectListItem{ Selected = string.IsNullOrEmpty(Model.Title), Text="",Value=""},
    new SelectListItem{ Selected = Model.Title.Equals("Mr"), Text="Mr",Value="Mr"},
    new SelectListItem{ Selected = Model.Title.Equals("Mrs"),   Text="Mrs",Value="Mrs"},
    new SelectListItem{ Selected = Model.Title.Equals("Miss"), Text="Miss",Value="Miss"},
    new SelectListItem{Selected = Model.Title.Equals("Ms"), Text="Ms",Value="Ms"}       
    });
}
@Html.DropDownListFor(m=>m.Title, list)
</td>
James McCormack
  • 9,217
  • 3
  • 47
  • 57
TheRealTy
  • 2,409
  • 3
  • 22
  • 32
  • did you try to use var list = new SelectList(...) ? because something like this works for me: Html.DropDownListFor(m=> m.Title, new SelectList(new string[] { "Select title", "Mr", "Miss"}, "Mr")); (selects Mr) – Spikolynn Mar 18 '11 at 01:27
  • can you use the debugger to confirm that Selected is being set to true on one of these items? – Robert Levy Mar 18 '11 at 01:27

2 Answers2

21

I had this problem with MVC 3 and it turned out that I had set ViewBag.Title on my View (using it for the page title). As soon as I changed it to ViewBag.PageTitle, the dropdownlist code started working : @Html.DropDownListFor(model => model.Title, Model.MySelectList)

The reason for this is that in MVC 2/3, any ViewBag / ViewData properties with the same name as those in the Model object get used in preference in DropDownListFor(), so you need to rename them to make sure they don't conflict. Because that seems really flaky, I just stopped using ViewBag entirely and now rely only on the View Model for passing stuff into the View.

The reason this problem is so prevalent is that ViewBag.Title is used in many introductory tutorials and demo code to set the HTML title element, and so inevitably gets adopted as a "best-practice" approach. However, Title is a natural Model property name for use in dropdowns on a "User Details" view.

James McCormack
  • 9,217
  • 3
  • 47
  • 57
  • 3
    I think this is a bug in MVC3. Any thing in the ViewData keys which has the same Model property name would cause this issue. Thank you you saved my day +1 – Wahid Bitar Dec 24 '11 at 12:54
  • Thanks! I nearly wasted so much time with this. – GrantVS Feb 03 '12 at 00:11
  • Thank you so much, I was getting crazy! – tsimbalar Jul 26 '12 at 09:24
  • This answer should be accepted. It's very helpful and you are lifesaver! +1 – nrodic Sep 21 '12 at 12:00
  • Uff, the time I spent looking for that. The only thing is, it seems that ViewBag/ViewData is actually used in preference to any SelectList that you pass to the DropDownListFor helper when setting the selected item. If a ViewBag property exists with the same name as your model project, it gets used, regardless of the list you pass in. Passing the list in a ViewModel makes no difference to this. – Paul Taylor Nov 28 '12 at 13:29
  • Sorry, what I meant is this: Don't use the ViewBag or ViewData at all, for anything, ever. If you're going to pass something to a View, pass it in the Model. – James McCormack Nov 28 '12 at 17:20
  • Saved me too - thanks! Warning: it works in MVC4. Perhaps the DDL no longer looks in ViewBag for the default? – MrBlueSky Jan 11 '13 at 10:08
  • Worked great for a value at the top node of my model, but I am still having difficulty figuring out how to get this to work for a value within a collection that I am iterating with a for loop. – iGanja Apr 12 '13 at 20:09
12

So it turns out that the only reason it doesn't work is because my field name is Title, I changed it to Prefix and my exact code works. Way too much time spent finding that out...

Here is working code.

<td>
    @{ var list = new List<SelectListItem>(new[] {
        new SelectListItem { 
            Selected = string.IsNullOrEmpty(Model.Prefix), 
            Text="",
            Value=""
        },
        new SelectListItem { 
            Selected = Model.Prefix.Equals("Mr"), 
            Text="Mr",
            Value="Mr"
        },
        new SelectListItem {
            Selected = Model.Prefix.Equals("Mrs"),
            Text="Mrs",
            Value="Mrs"
        },
        new SelectListItem {
            Selected = Model.Prefix.Equals("Miss"), 
            Text="Miss",
            Value="Miss"
        },
        new SelectListItem {
            Selected = Model.Prefix.Equals("Ms"), 
            Text="Ms",
            Value="Ms"
        }       
      });
    }
    @Html.DropDownListFor(m => m.Prefix, list)
</td>
Sergi Papaseit
  • 15,999
  • 16
  • 67
  • 101
TheRealTy
  • 2,409
  • 3
  • 22
  • 32
  • 2
    It's because you're probably already using a property called Title in your ViewBag / ViewData. I recommend changing your ViewBag / ViewData property name, not your model property name. In fact, stop using ViewBag / ViewData altogether cos it's horrible :) – James McCormack Jul 19 '12 at 12:38
  • Thank you so much, I had the same issue, and I was getting crazy! – tsimbalar Jul 26 '12 at 09:24
  • @JamesMcCormack "horrible" is such a great term. How should we send other data to our views that is not part of our strongly typed model? – iGanja Apr 12 '13 at 20:11
  • 1
    @iGanja create a class that contains everything you need for the view. The concept is known as a ViewModel. – AaronLS May 12 '13 at 01:50
  • @AaronLS So you would recommend I add my page title to my data model? (eg "a class" with "everything [I] need") ...and there goes the whole concept of decoupling my view from my model? nah, don't like that one. I may use my data model as a base class for "everything" I need. But really what I was asking is WHY using the ViewBag is so "horrible"? Without some sort of justification, it's just a silly empty statement. – iGanja May 12 '13 at 02:18
  • 1
    @iGanja It's horrible because it is loosely typed. You don't have to go far to find lots of articles ont he benefits of strong typing. "there goes the whole concept of decoupling my view from my model?" Actually using a ViewModel improves the decoupling, by making your view not dependent on your model. For example, often I have a ViewModel that is used by both the Create and Edit pages. If the Model changes, I only need to change the mapping to the ViewModel. I do not have to change the View in anyway. If you use your Model classes directly in your Views, then you have tight coupling. – AaronLS May 12 '13 at 02:53
  • @iGanja I personally though wouldn't say it is "horrible". I think that is a overly strong statement. But still the ViewBag should be avoided if possible. – AaronLS May 12 '13 at 02:54
  • String literals used as keys in a system where no error occurs when you make a typo, is asking for trouble. As @AaronLS said, the benefits of strong typing are also lost. I stand by "horrible" :) But don't just take my word for it - ask Mr Dimitrov! http://stackoverflow.com/questions/4705426/whats-the-difference-between-viewdata-and-viewbag – James McCormack Jan 30 '14 at 15:20