2

I currently have an application with a home page that shows a list of ten movies based on the date they were "created", or entered into the database. I would also like to show a list of the top ten movies based on the rating of each movie. Is there a way to pass in another model or alter my current ViewModel to do this? Here is the Index section of my Home Controller:

    public ActionResult Index()
    {
        var model =
            _db.Movies
                .OrderByDescending(m => m.DateEntered)
                .Take(10)
                .Select(m => new MovieListViewModel 
                {
                    Id = m.Id,
                    Title = m.Title,
                    Genre = m.Genre,
                    ReleaseDate =  m.ReleaseDate,
                    CountOfReviews = m.Reviews.Count()
                });

        return View(model);

    }

And the ViewModel being passed in:

public class MovieListViewModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Genre { get; set; }

    [Display(Name="Year Released")]
    public DateTime ReleaseDate { get; set; }
    public int CountOfReviews { get; set; }
}
Ron Saylor
  • 381
  • 6
  • 19
  • You can compose a single view model that contains the two result sets. This becomes a little more tricky with read/write scenarios, but for displaying information it is very straightforward. – Tim M. May 24 '13 at 19:02

5 Answers5

7

Create a model that encompasses both lists:

public class MovieListViewModel
{
  public List<MovieModel> Top10ByCreated { get; set; }
  public List<MovieModel> Top10ByRating { get; set; }
}

public class MovieModel
{
  public int Id { get; set; }
  public string Title { get; set; }
  public string Genre { get; set; }

  [Display(Name="Year Released")]
  public DateTime ReleaseDate { get; set; }
  public int CountOfReviews { get; set; }
}

Then in your controller:

var model = new MovieListViewModel();

model.Top10ByCreated = ...
model.Top10ByRating = ...

return View(model);

In your view, use MovieListViewModel as your model and use your two lists as needed.

Matt Houser
  • 33,983
  • 6
  • 70
  • 88
2

Just create another viewmodel, with two properties for the two lists:

public class MovieIndexViewModel
{
    public IEnumerable<MovieListViewModel> TopTenByDate { get; set; }
    public IEnumerable<MovieListViewModel> TopTenByRating { get; set; }
}

In the controller you can create this viewmodel and pass the two lists:

public ActionResult Index()
    {
        var vm = new MovieIndexViewModel();

        vm.TopTenByDate = ....;
        vm.TomTenByRating = ...;

        return View(vm );

    }
Pbirkoff
  • 4,642
  • 2
  • 20
  • 18
1

You can compose a single view model that contains the two result sets. The controller then instantiates the parent type and populates the child collections as you see fit.

public sealed class HomeViewModel{
    public MovieListViewModel TopTenByRating { get; set; }
    public MovieListViewModel TopTenByDate { get; set; }
}

public ActionResult Index()
{
    var model = new HomeViewModel();

    model.TopTenByDate =
        _db.Movies
            .OrderByDescending(m => m.DateEntered)
            .Take(10)
            .Select(m => new MovieListViewModel 
            {
                Id = m.Id,
                Title = m.Title,
                Genre = m.Genre,
                ReleaseDate =  m.ReleaseDate,
                CountOfReviews = m.Reviews.Count()
            });

    model.TopTenByRating = // something else

    return View(model);
}

For more complex scenarios, I prefer a dedicated composer that is responsible for setting up the view model (rather than having all the logic in the action method).

For a simple scenario like this, setting it up in the controller is the easiest way. If you find yourself needing to reuse the query logic, consider abstracting it to a helper class.

Community
  • 1
  • 1
Tim M.
  • 53,671
  • 14
  • 120
  • 163
0

A different approach would be to create the main view and get it to render the results of 2 action methods returning 2 partial views each typed to one of the models.

JTMon
  • 3,189
  • 22
  • 24
0

You have different options you can use anyone of them

Use ViewModel

For view model you have to create a class and in this class you will define all models as properties of this class.Here are two classes.

public class EmployeeDetails
{
    [Required]
    [Display(Name = "Name")]
    public string Name { get; set; }

}

public class Employee
{
    public int Id { get; set; }
}

Here is viewmodel

public class ViewModel
{
    public Employee emp { get; set; }
    public EmployeeDetails empdet{ get; set; }
}

Now in Controller you will do like this

public ActionResult About()
{
        ViewModel vm = new ViewModel();
        vm.emp = new Employee();
        vm.empdet = new EmployeeDetails();
        return View(vm);
}

And in view you will receive it like this

@model ViewModel

Use Tuple

Tuple is used to store different types.You can store your required classes object in it and pass to view

In controller

Tuple<int, string> tuple = new Tuple<int, string>(1, "Hello world");
return View(tuple);

In view you will receive it like this

@model Tuple<int,string>
Mairaj Ahmad
  • 14,434
  • 2
  • 26
  • 40