How to use multiple models in one view for ASP.NET MVC?

I read similar questions about SO, but I can not understand this problem, which is specific to DBContext objects (I think). Here is some dummy code to illustrate.

I have the following code in an Index () action:

public ActionResult Index() { AnimalDBContext db = new AnimalDBContext(); return View(db.Dogs); } 

I have the following code for my models:

  public class Dog { public int ID { get; set; } public string name { get; set; } public string breed { get; set; } } public class AnimalDBContext : DbContext { public DbSet<Dog> Dogs { get; set; } } 

In my opinion, I have the following:

 @model IEnumerable<AnimalProject.Models.Dog> @foreach (var d in Model) { <h3>@d.name</h3> <h2>@d.breed</h2> } 

Everything works fine, the view will go through every dog ​​in my database. However, I have another DBContext dataset from another table that I want in the same view. I want to be able to list each item in the database for this table.

This is what I want if you catch my drift:

 @model IEnumerable<AnimalProject.Models.Dog> @model IEnumerable<AnimalProject.Models.Cat> @foreach (var d in Dog) { <h3>@d.name</h3> <h2>@d.breed</h2> } @foreach (var c in Cat) { <h3>@c.name</h3> <h2>@c.breed</h2> } 

I tried to group classes together and use a partial view, but apparently you cannot have another model in a partial view, because I always get an error message:

"The model element passed to the dictionary is of type 'System.Data.Entity.DbSet 1[AnimalProject.Models.Dog]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable 1 [AnimalProject.Models. Cat] '".

So, how can I use several models in my view so that both get the data that I want from individual tables in the database?

+6
source share
3 answers

How about creating a custom view model class:

 public AnimalModel { public IEnumerable<Dog> Dogs { get; set; } public IEnumerable<Cat> Cats { get; set; } } 

Fill this model in Index and pass it to the view that AnimalModel will expect instead of enumerations.

Edit:

Filling the model:

 public ActionResult Index() { using (var db = new AnimalDBContext()) { var model = new AnimalModel { Dogs = db.Dogs.ToList(), Cats = db.Cats.ToList() }; return View(model); } } 

View (I have never used Razor, so I hope this is correct):

 @model AnimalProject.Models.AnimalModel @foreach (var d in Model.Dogs) { <h3>@d.name</h3> <h2>@d.breed</h2> } @foreach (var c in Model.Cats) { <h3>@c.name</h3> <h2>@c.breed</h2> } 
+12
source

A model is just an object similar to any other object in C # (or VB)

Thus, you can transfer any object that you want to view, even complex ones. If you need to imagine a lot of things, then create a presentation model (a model only for the needs of the view) that contains everything you want to present, and pass that into the view. Then, from within the view, you gain access to the individual properties of the model in different parts of the view to represent them. An example of this approach is the model of the animal Ladislav Mrnka. You put dogs and cats there, and then pass them on for viewing. You will say that your model is now an AnimalModel type, etc. Etc....

So, since the model is just an object, and if you are lazy enough not to want to create another custom view model, you can pass all of your dbcontext as a model for that kind.

controller

 public ActionResult Index() { return View(new AnimalDBContext()); // We pass a new instance of the dbcontext to the view } 

View

 @model AnimalProject.AnimalDBContext // we declare that our model is of type AnimalDBContext @foreach (var d in Model.Dogs) // We reference the dbcontext sets directly { <h3>@d.name</h3> <h2>@d.breed</h2> } @foreach (var c in Model.Cats) // We reference the dbcontext sets directly { <h3>@c.name</h3> <h2>@c.breed</h2> } 

Now you have stated that your "Model" object will be AnimalDBContext. So you can access all AnimalDBContext properties, sets, etc. Directly from your view. This may not be the best abstraction for accessing data, but look how simple your controller has become! :) You just throw the whole world into a presentation and let it decide which parts to choose and present ... Of course, this is for simple scenarios. If you need more complex things, you will eventually have to revert to custom view models.

+3
source

The only solution to this problem that I have found so far is to pull both models into the ViewBag and then display partial views for parts that use only one model. Of course, it only works if the partial views are separated - as in your case. This allows you to strictly typify partial views compared to directly accessing the contents of the ViewBag .

The solution is similar to Ufuk's answer. First put the data in the ViewBag from the controller:

 ViewBag.Dogs = db.Dogs; ViewBag.Cats = db.Cats; 

Then draw a partial view from the view:

 @Html.Partial("_ListDogs", ViewBag.Dogs) @Html.Partial("_ListCats", ViewBag.Cats) 

And each partial view will be along the lines of the following (example: _ListDogs.cshtml ):

 @model IEnumerable<AnimalProject.Models.Dog> @foreach (var d in Model) { <h3>@d.name</h3> <h2>@d.breed</h2> } 
0
source

Source: https://habr.com/ru/post/886942/


All Articles