3

It seems like this question has been asked too many times. But this is driving me nuts.

This is my (simplified) model.

public class UserEditModel
{
    [Required]
    public string Title { get; set; }

    private IEnumerable<SelectListItem> _titleList;
    public IEnumerable<SelectListItem> TitleList
    {
        get { return _titleList.Select(x => new SelectListItem {
                            Selected = (x.Value == Title), 
                            Text = x.Text,
                            Value = x.Value
                        });
        }
        set { _titleList = value; }
    }
}

The Text and Value properties of each SelectListItem in the TitleList member are identical. For example:

new SelectListItem { Text = "Mr", Value = "Mr"  }

When the following code is posted, the correct Title value is bound to the model, but whenever the model is pushed to the view in response to a POST or a GET, the selected value is not set on the dropdownlist, even though all the intellisense shows that the correct values are present.

@Html.DropDownListFor(x => x.Title, Model.TitleList)

I have ensured that the code is correct based on several articles and several SO answers, so I am stumped.

Any suggestions?

Update:

For completeness, this is the action and supporting method:

[HttpGet]
public ActionResult Edit(int id)
{
    var user = _userService.Get(id);

    var model = new UserEditModel()
    {
        ...
        Title = user.Title,
        TitleList = ListTitles()
    };

    return View(model);
}

private IEnumerable<SelectListItem> ListTitles()
{
    var items = new[] {
            new SelectListItem() {Text = "Mr", Value = "Mr" },
            new SelectListItem() {Text = "Mrs", Value = "Mrs"},
            new SelectListItem() {Text = "Ms", Value = "Ms"},
            new SelectListItem() {Text = "Miss", Value = "Miss"},
            new SelectListItem() {Text = "Professor", Value = "Professor"},
            new SelectListItem() {Text = "Dr", Value = "Dr" }
        };

    return items;
}

As you see there is nothing fancy, just a straightforward implementation.

Digbyswift
  • 10,310
  • 4
  • 38
  • 66

3 Answers3

2

You need to add ModelState.Clear() because by default when returning a view from a post action, it thinks it has failed validation, so uses the values in ModelState and not the values in the Model. Many people think this is actually a bug in MVC, but it's by design:

ASP.NET MVC assumes that if you’re rendering a View in response to a HttpPost, and you’re using the Html Helpers, then you are most likely to be redisplaying a form that has failed validation. Therefore, the Html Helpers actually check in ModelState for the value to display in a field before they look in the Model. This enables them to redisplay erroneous data that was entered by the user, and a matching error message if needed.

Link

Mathew Thompson
  • 55,877
  • 15
  • 127
  • 148
  • The problem isn't with the POST/ModelState. The selected value isn't set ever, on a POST or GET. My mention of the POST was to show the model was set up correctly and so was unlikely to be a problem with the model. – Digbyswift Apr 17 '13 at 08:32
  • @Digbyswift If you can see it in the action it's going to right before it's hitting the view, it is **almost certainly** `ModelState`. Did you try adding the `.Clear`? – Mathew Thompson Apr 17 '13 at 08:35
  • @Digbyswift Could you also post your action? Just to make sure nothings up with that. – Mathew Thompson Apr 17 '13 at 08:36
  • I've updated the answer. You'll see it's pretty basic which is why it is bugging me so much. – Digbyswift Apr 17 '13 at 08:43
  • Hmm that's weird, all looks fine. You say when debugging it you can verify the value in `model.Title` before it hits the view yeah? – Mathew Thompson Apr 17 '13 at 08:48
  • Yes, I can manually create a dropdownlist with a loop matching the correct option against the `Model.Title` property. – Digbyswift Apr 17 '13 at 08:52
  • Hmmm, can you post the rest of your view? I think I may know the issue. – Mathew Thompson Apr 17 '13 at 08:59
  • No need. I figured out the answer. Looks like `Title` was a reserved word. Thanks for your help. – Digbyswift Apr 17 '13 at 09:00
  • This was driving me crazy. I added ModelState.Clear() and that fixed it. I would have never thought of that. Thank you! – gabnaim Sep 13 '13 at 20:39
2

Well, it seems there is actually nothing wrong with the code, just the name of the Title property in the model.

It looks like Title is a reserved word and replacing it with TitleX or more appropriately Salutation makes everything work fine.

Digbyswift
  • 10,310
  • 4
  • 38
  • 66
  • Thanks fella. I've had this exact same problem - even used the same property names as you. Just spent a couple of hours pulling my hair out over this. As we say down our way: "what a crock of shit..." – kenxl Feb 18 '14 at 13:27
  • Same problem here, must catch a lot of people out. However I've now got another drop down not selecting the right value. I can see the value set to the Model in the template but it's not getting selected. Every other drop down works fine and I can't see any difference in the code. – blues_driven Sep 29 '15 at 09:19
  • http://stackoverflow.com/questions/2278056/dropdownlistfor-not-selecting-value Fixed! I was assigning a ViewBag property with the same name as the model property, which is a big no-no apparently. – blues_driven Sep 29 '15 at 09:23
0

Are you sure you retrieve the selectlist item appropriately in the controller? For me it is working fine. I would use a get method instead of a property ( GetTitleList(string value) ), to avoid mistakes in getting the selectionlist farther along in your code.

Tim
  • 89
  • 7
  • Regardless of the implementation, if the code works for you it should work for me shouldn't it? And yes, as I say in the OP the values are all correct. It's a mystery! – Digbyswift Apr 17 '13 at 08:37