MVC 3: DropDownList on an Edit Form for an object that is a property of a ViewModel

asp.net-mvc, asp.net-mvc-3, c#, entity-framework-4, razor

Solution

It's your `DropDownList` declaration that's incorrect. Try this instead:

@Html.DropDownListFor(m => m.season.ClubId, ViewBag.ClubId)

But really, you should put that select list in your model:

public SelectList Clubs { get; set; }

Then populate it in your controller:

Model.Clubs = new SelectList(clubs, "ClubId", "Name", season.ClubId);

Then you can do:

@Html.DropDownListFor(m => m.season.ClubId, Model.Clubs)

Problem

Overview: I'm trying to use a ViewModel that has a property that is the model class that I'm trying to edit. I've seen the edit form work using the MVC scaffolding edit forms when editing a model directly, however I am trying to use a ViewModel that contains the model being edited. Everything works except for the saving of a field that's displayed in a DropDownList. Explanation: I've attempted to use the scaffolding features of MVC 3 to create an edit form for a model. In the MVC Music Store tutorial, this is done for the Edit page of an `Album`, in the `StoreManagerController`. Within that page, they have two drop downs for Genre and Artist. Each looks similar to this in the view:- ``` <div class="editor-label"> @Html.LabelFor(model => model.GenreId, "Genre") </div> <div class="editor-field"> @Html.DropDownList("GenreId", String.Empty) @Html.ValidationMessageFor(model => model.GenreId) </div> ``` As far as I can tell, these have their options filled out in the controller using the ViewBag. ``` ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId); ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId); ``` Working with the Model directly In my code, I managed to do the same with an object that's being saved to the DB through Entity Framework. Model ``` public class Season { public int SeasonId { get; set; } public int ClubId { get; set; } public Club Club { get; set; } } ``` Code in Controller ``` ViewBag.ClubId = new SelectList(clubs, "ClubId", "Name", season.ClubId); ``` View ``` <div class="editor-label"> @Html.LabelFor(model => model.ClubId, "Club") </div> <div class="editor-field"> @Html.DropDownList("ClubId", String.Empty) @Html.ValidationMessageFor(model => model.ClubId) </div> ``` This works fine. Working with the View Model However now I have realised that the page needs more text displayed than what is available in the model I'm editing. I was hoping to create a special View Model, with the edited model (season) and the extra text I want to display. ViewModel ``` public class EditSeasonViewModel { public string PlayerName {get; set;} public string SummaryText {get; set;} public int PlayerId {get; set;} public Season season {get; set;} } ``` I did this, changed the controller to have the HttpGet and HttpPost methods use the new ViewModel, changed the View to accept the new ViewModel, and changed the all 'EditorFor' methods in the view to use model.season.MyProperty. Code in Controller ``` ViewBag.ClubId = new SelectList(clubs, "ClubId", "Name", seasonVM.season.ClubId); ``` Code in View ``` <div class="editor-label"> @Html.LabelFor(model => model.season.ClubId, "Club") </div> <div class="editor-field"> @Html.DropDownList("ClubId", String.Empty) @Html.ValidationMessageFor(model => model.season.ClubId) </div> ``` When debugging the HttpPost method, all of the values for season properly exist, except for the ClubId value which should come from the DropDropList. I haven't changed the DropDownList in the View at all from the way it was when we were using the Model directly. Question: My question is, what do I need to change to get the ClubId to be saved properly when using this new `EditSeasonViewModel`? Also, how does the ViewBag.ClubId in the HttpGet method in the controller match to the DropDownList in the View, and then have it's value passed back to the HttpPost method?

Original source