0

In model there are two tables. Books and Reviews of Books. Each book has some (or none) review with score point. In the Index controller action would like to pass list of books to view with additional column as average number of score points to that book.

Typically without additional column Index Body looks like this:

public ActionResult Index()
{
    return View(db.Books.ToList());
}

and View use that model

@model IEnumerable<NameOfSolution.Models.Books>

What is the proper way to add more info? Build a different query like this(?) :

(without additional column):

public ActionResult Index()
{
    var BooksList = from b in db.Books
                    select new 
                    {   
                        b.Id,
                        b.BookRef,
                        b.BookTitle,
                        b.Authors
                    };

   // return View(db.Books.ToList());
    return View(BooksList.ToList());
}

after that exception will be thrown:

The model item passed into the dictionary is of type System.Collections.Generic.List1[<>f__AnonymousType14[System.Int32,System.Int32,System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[NameOfSolution.Models.Books]'`.

The question is: what is the proper approach to solve this? Should I do some cast var BooksList to more generic model or add separate file class to solution and use it like strong typed model?

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • something like this is working `public ActionResult Index() { IEnumerable BooksList = db.Books.Where(p => p.BookTitle.StartsWith("H")); return View(BooksList.ToList()); }` – Przemyslaw Staniszewski Dec 27 '14 at 13:26

3 Answers3

0

View expected list of NameOfSolution.Models.Books objects but you passed list of anonymous classes.

Use select new NameOfSolution.Models.Books

STO
  • 10,390
  • 8
  • 32
  • 32
  • I got Error 1 Cannot initialize type 'NameOfSolution.Models.Books' with a collection initializer because it does not implement 'System.Collections.IEnumerable'. After include Yours change and { Id = b.Id, BookRef = b.BookRef, BookTitle = b.BookTitle, Authors = b.Authors }; i have got The entity or complex type 'NameOfSolutionModel.Books' cannot be constructed in a LINQ to Entities query. – Przemyslaw Staniszewski Dec 27 '14 at 13:14
  • [that is why I can't](http://stackoverflow.com/questions/5325797/the-entity-cannot-be-constructed-in-a-linq-to-entities-query) – Przemyslaw Staniszewski Dec 27 '14 at 13:18
  • I guess you could call ToList before constructing view models (in case if you Book entity doesn't have extra data) – STO Dec 28 '14 at 22:03
0

The view model type and declared model for view i.e. @model IEnumerable<NameOfSolution.Models.Books> are different. you may use some tings like below

var BooksList = from b in db.Books
                    select new NameOfSolution.Models.Books
                    {   
                        b.Id,
                        b.BookRef,
                        b.BookTitle,
                        b.Authors
                    };
bijayk
  • 556
  • 3
  • 18
  • If I do this compiler will return: Error 1 Cannot initialize type 'NameOfSolution.Models.Books' with a collection initializer because it does not implement 'System.Collections.IEnumerable'. Model was generated from database for EF – Przemyslaw Staniszewski Dec 27 '14 at 12:54
0

This is typically done by a view model. In its most simple form:

public class BookViewModel
{
    public string BookTitle { get; set; }
    public double? AverageRating { get; set; }
}

...

var booksList = from b in db.Books
                select new BookViewModel
                {   
                    BookTitle = b.BookTitle,
                    AverageRating = b.Reviews
                                     .Average(r => r.Score)
                };

AverageRating is a nullable type because there may be books without reviews, so the view model should be able to hold null values.

Now of course the @model should be IEnumerable<BookViewModel>.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291