0

I am building the classic movie catalog project.

I have a many-to-many with movies and genres so that I can list the genres in movies and vice-versa, etc.

I am having trouble doing that with my models. I can use models to relate one to view, but need ViewBag to display the other.

I am a beginner and any help conquering advanced ViewModels would be greatly appreciated.

Ill use my create() movie method as an example:

My MovieController:

[Authorize(Roles = "Admin")]
[HttpGet]
 public ActionResult Create()
        {
            ViewBag.Genres = db.Genres.Select(
                g => new GenreToMovie
                {
                    id = g.Id,
                    Name = g.Name,
                    Checked = false
                }).ToList();
            return View();
        }

...

 //List Genre Movies
        private void MovieLister(Genre genre)
        {
            //Assign Movies to Genre List
            ViewBag.Movies = db.Movies.Select(
                m => new MovieToGenre
                {
                    id = m.Id,
                    Title = m.Title,
                    Year = m.Year,
                    Checked = db.Genres.FirstOrDefault(g => g.Id == genre.Id).Movies.Any(movie => movie.Id == m.Id)
                }).ToList();

My Movie Model:

namespace MovieSite.Models
{
    public class Movie
    {
        public int Id { get; set; }

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

        [Required]
        public int Year { get; set; }
        public virtual ICollection<Genre> Genres { get; set; }

        public Movie() { }

        public Movie(string title, int year)
        {
            Title = title;
            Year = year;
            Genres = new List<Genre>();
        }

    }

}

My MovieViewModels (A bad name I'm sure, its where I keep my GenreTomMovie ViewModel:

namespace MovieSite.Models
{
    //Assign Genres to Movies
    public class GenreToMovie
    {
        public int id { get; set; }
        public string Name { get; set; }
        public bool Checked { get; set; }
    }

    //Assign Movies to Genres
    public class MovieToGenre
    {
        public int id { get; set; }
        public string Title { get; set; }
        public int Year { get; set; }
        public bool Checked { get; set; }
    }

    public class MovieViewModel
    {
        public int MovieID;
        public string Title { get; set; }
        public int Year { get; set; }

        public MovieViewModel() { }

        public MovieViewModel(int id, string title, int year)
        {
            MovieID = id;
            Title = title;
            Year = year;
        }
    }

}

My Create View:

@model MovieSite.Models.Movie
@{
    ViewBag.Title = "Create Movie";
}
<h2>Add Movie</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <label style="color:red" id="errormsg"></label>
        <div class="form-group">
            @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control", id = "movieTitle" } })
                @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Year, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Year, new { htmlAttributes = new { @class = "form-control", id = "movieYear" } })
                @Html.ValidationMessageFor(model => model.Year, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Genres, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10" style="height:250px; width:400px; overflow-y:scroll">
                <br />
                @{
                    List<MovieSite.Models.GenreToMovie> moviegenres = ViewBag.Genres;
                    foreach (var genre in moviegenres.OrderBy(m => m.Name))
                    {
                        <ul style="padding:0px">
                            <input type="checkbox" name="SelectedGenres" value="@genre.id" @Html.Raw(genre.Checked ? "checked=\"checked\"" : "") />
                            @genre.Name
                        </ul>
                    }
                }
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default"/>
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Manage")
</div>

You can see just below halfway on my views I have a viewbag:

@{
                    List<MovieSite.Models.GenreToMovie> moviegenres = ViewBag.Genres;
                    foreach (var genre in moviegenres.OrderBy(m => m.Name))
                    {
                        <ul style="padding:0px">
                            <input type="checkbox" name="SelectedGenres" value="@genre.id" @Html.Raw(genre.Checked ? "checked=\"checked\"" : "") />
                            @genre.Name
                        </ul>
                    }
                }

To display my genres, and I don't want that. I have tried to make a number of viewmodels to combine data, but I get nowhere. I've been banging my head against the table for a couple days now and can't find a clear example online. Please Obi-Wan, you're my only hope.

I just need one clean example and I can figure this out. I just can't unlock it right now. Thanks for your time and help.

EDIT:

With the suggestion in the comments I made a viewmodel to pass through: public class MovieAddVM

{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Year { get; set; }
    public string Title { get; set; }
    public bool Checked { get; set; }

    public virtual ICollection<Genre> Genres { get; set; }

    public MovieAddVM()
    {
        GenreList = new List<GenreToMovie>();
    }
    public List<GenreToMovie> GenreList { get; set; }

}

It registers with my views, but does not populate a list of genres. How do I query my genres and attribute that list to the viewmodel? I'm sorry I am very confused about all this.

Mr9mm
  • 19
  • 3
  • Refer [this answer](https://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable/29554416#29554416) for a typical example –  Apr 24 '18 at 23:59
  • I got it because of this. Thank you! – Mr9mm Apr 25 '18 at 05:18

0 Answers0