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.