mardi 5 mai 2015

Implementing bound dropdown list in MVC5 - Post action returns null values

I appear to be having some problems with dropdown list populating and binding in MVC. The simple example I have has a List of Movies with a Genre item that is populated with a drop down.

I pass across a Select List with the items to populate the drop down but appear to be running into problems when the post action is happening.

The problems appear to be : The ViewModel being returned appears to return the GenreList as null on the Post action. The Genre does not appear to be set so that after the edit -the dropdown list is populated correctly.

I cannot seem to find a good answer for this and have been trying quite a few examples but seem to be going round in circles. Would like to try and get this most basic of dropdown list edit example working so I can see how this should be implemented.

Model Classes

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace Test.Models
{
public class Genre
{
    [Key]
    public int Id { get; set; }
    public string Description { get; set; }
}


public class Movie
{
    [Key]
    public int MovieID { get; set; }

    public string Name { get; set; }


    public Genre MovieGenre { get; set; }
}

public class MovieViewModel
{
    public Movie MovieItem { get; set; }
    public SelectList GenreList{ get; set; }

}
}

Controller Code

namespace Test.Controllers
{
    public class MoviesController : Controller
    {

        private DataContext _dc = new DataContext();

        // GET: Movies
        public ActionResult Index()
        {
            var x = from m in _dc.Movies
                    select m;

            return View(x.ToList());
        }

        // GET: Movies/Edit/5
        public ActionResult Edit(int id)
        {

            var x = from m in _dc.Movies
                    where m.MovieID == id
                    select m;

            var l = from m in _dc.Genres
                    select m;

            var y = new MovieViewModel
            {
                GenreList = new SelectList(l.ToList(), "ID", "Description"),
                MovieItem = x.FirstOrDefault()
            };

            return View(y);
        }

        // POST: Movies/Edit/5
        [HttpPost]
        public ActionResult Edit(int id, MovieViewModel m)
        {
            // PROBLEM: GenreList in model is now not populate for return

            if (ModelState.IsValid)
            {

                var movie = _dc.Movies.Find(id);
                movie.Name = m.MovieItem.Name;
                movie.MovieGenre = m.MovieItem.MovieGenre;
                // PROBLEM: The MovieGenre does not appear to be saved correctly 
                //          when you make the edit and go back to that record after saving
                //          the dropdown is not populated.
                _dc.SaveChanges();
                return RedirectToAction("Index", "Movies");
            }



            return View(m);
        }


    }
}

Razor View Code

@model Test.Models.MovieViewModel

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.MovieItem.MovieID)

        <div class="form-group">
            @Html.LabelFor(model => model.MovieItem.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.MovieItem.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.MovieItem.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div>
                @Html.LabelFor(m => m.GenreList, "Genre:")
                @Html.DropDownListFor(m => m.MovieItem.MovieGenre.Id, (IEnumerable<SelectListItem>) Model.GenreList)


            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Aucun commentaire:

Enregistrer un commentaire