So as I wanted to have a deeper understanding. I added a little bit more functionality to the MSFT tutorial on MVC4 that you can find here (http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4)
The model is very simple. You have movies and directors. Every movie has 1 director max.
I want the user to be able to assign a director to a movie from a drop down list and save it but somehow the movie gets saved with a null Director_ID field in the database.
Here are my simple models:
public class Movie
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
public decimal Price { get; set; }
public string Ranking { get; set; }
public Director Director { get; set; }
}
public class Director
{
public int ID { get; set; }
public string Name { get; set; }
}
When the movie table gets generated it comes with a Director_ID field. Sweet!
I would like the user to select a director while editing a movie form a drop down list so in the movie edit view I managed to bind a drop down list to a list of all directors obtained form the database
<div class="editor-field">
@Html.DropDownListFor(model => model.Director.ID, ViewBag.Directors as List<SelectListItem>, "All")
</div>
Controller:
//GET
public ActionResult Edit(int id = 0)
{
var DirectorsList = new List<SelectListItem>();
var DirQuery = from d in db.Directors select d;
foreach (var d in DirQuery)
{
DirectorsList.Add(new SelectListItem { Value = d.ID.ToString(), Text = d.Name });
}
ViewBag.Directors = DirectorsList;
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
I get my list of all directors in my drop down. All right!
Now when I save the movie :
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
movie.Director = db.Directors.Find(movie.Director.ID);
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
The argument movie that the Edit method receives comes with a Director property (as I specified in the model), when I browse into it I see the two properties form director: "ID": which comes with the proper value that the user selected form the drop down and "Name": set to null. As you can see in the code I pick the whole director object form the database matching the drop down value and save it
The problem is that when saving the movie, the foreign key on Movies table (Director_ID) never gets updated.
What am I doing wrong? Is there any better approach for doing this?
Make Id of the Director part of your model, like
public class Movie
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
...
public int DirectorId { get; set; }
public virtual Director Director { get; set; }
}
Then in your controller:
//GET
public ActionResult Edit(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
ViewBag.DirectorId = new SelectList(db.Directors, "DirectorId", "Name", movie.DirectorId);
...
}
And in your view:
<h2>Edit</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
...
<div class="editor-label">
@Html.LabelFor(model => model.DirectorId, "Director")
</div>
<div class="editor-field">
@Html.DropDownList("DirectorId", String.Empty)
@Html.ValidationMessageFor(model => model.DirectorId)
</div>
...