There are 2 models, users and programs (there is a description of the models in this question ). I want to display in the tables all the programs from the database, and after all the users.

Made 1 controller with 2 actions and 2 view.

Context db = new Context(); public ActionResult Progs() { IEnumerable<Prog> progs = db.Progs; IEnumerable<User> users = db.Users; ViewBag.Progs = progs; ViewData["Users"] = users; return View(); } public ActionResult Users() { IEnumerable<User> users = db.Users.Include(u => u.Prog); return View(users); } <table class="table table-bordered"> <thead> <tr> <th>Номер строки</th> <th>Название программы</th> </tr> </thead> <tbody> @foreach (var item in ViewBag.Progs) { <tr> <th scope="row">@item.Id</th> <td>@item.Name</td> </tr> } </tbody> </table> @Html.Partial("Users", ViewData["Users"]); @model IEnumerable<WebApplication3.Models.User> <table class="table table-bordered"> <thead> <tr> <th>Номер строки</th> <th>Название программы</th> <th>Фамилия пользователя</th> <th>Программа пользователя</th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <th scope="row">@item.Id</th> <td>@item.Surname</td> <td>@item.Age</td> <td>@item.Prog.Name</td> </tr> } </tbody> </table> 

View User goes as partial. And when the controller action for programs is called, users should also be drawn, but since there is no data for users, there is nothing to draw from, because the controller of users does not move, as in such cases do? Trying out the action of the programs via ViewBag also transfer users for drawing, but it did not work out. Can somehow you can use action users in this case? Or does it have to be done like that? Please tell me, just starting to learn mvc.

  • Updated the answer, read it and linked questions. - AK
  • @AK, as I understood the CompositeProgsAndUsersViewModel model, is a viewmodel. Could you set an example of how it should look like well, the classes themselves, I don’t understand how the viewmodels are made, thanks in advance. - Andrei
  • I added another answer to the update, but for the future I recommend not to push twenty topics into one question at once, think over them carefully and publish them as separate topics. - AK

1 answer 1

@ Html.Partial () has an overload in which you can specify data, and not just the name of the view.

If you want to display all the programs and for each indicate all users of these programs, then you need something in the spirit of:

 public ActionResult ProgsWithUsers() { IEnumerable<Prog> progs = db.Progs.Include(x => x.Users).ToArray(); return View(progs); } 

In the view:

 @model IEnumerable<WebApplication3.Models.Prog> <table class="table table-bordered"> <thead> <tr> <th>Номер строки</th> <th>Название программы</th> <th>Пользователи</th> </tr> </thead> <tbody> @foreach (var program in Model) { <tr> <th scope="row">@program.Id</th> <td>@program.Name</td> </tr> @if(program.Users.Count() > 0) { <td>@Html.Partial("Users", program.Users)</td> } else { <td>–</td> } } </tbody> </table> 

Well, in the partial view:

 @model IEnumerable<WebApplication3.Models.User> @foreach (var user in Model) { <div>@user.Surname</div> } 

Update. If you need to make a conclusion first of all programs, and then of all users, then there are options.

The most obvious and simple. Select data in one action:

 public ActionResult CompositeProgsAndUsers() { IEnumerable<Prog> progs = db.Progs; IEnumerable<User> users = db.Users; var model = new CompositeProgsAndUsersViewModel { Progs = progs, Users = users, } return View(model); } 

The view is based on the CompositeProgsAndUsersViewModel model and contains a call to two partial ones:

 @model IEnumerable<CompositeProgsAndUsersViewModel> @Html.Partial("Progs", Model.Progs) @Html.Partial("Users", Model.Users) 

What is convenient this option - the fact that the view is obtained thin, point and can be reused.

Partial representations will have as a model IEnumerable and IEnumerable, respectively (write yourself, the principle you already seem to understand)

If you want to display users with programs, see the code above with .Include (x => x.Progs).

You can also drop the model class and just cram everything into the viewbag (you have the code above, I just don’t understand what prevented everything from being put into the ViewBag, and not shoving it either in the ViewBag or in ViewData; perhaps there are some limitations, o which I have already forgotten, because I don’t like to use viewbag / viewdata - but so far this approach seems to me inconsistent , you decide either to go there or here)

Another option is to call the action inside the view via the ChildActionOnly mechanism (in my opinion, it may be less appropriate).

And for asp.net core there is a new way - through inject (see the answer of Pavel Mayorov in this topic ).

Update 2. Your specific ViewModel will look like this:

 public class CompositeProgsAndUsersViewModel { public IEnumerable<Prog> Progs { get; set; } public IEnumerable<User> Users { get; set; } } 

I am a supporter of writing separate ViewModel , and I do not use domain classes as view models.

As an example, I always cite the RegisterViewModel model from the ASP.NET Identity set (if identity is enabled in your asp.net project, look at the code) when the model has password and password confirmation fields:

 public class RegisterViewModel { [Required] [Display(Name = "UserName")] public string UserName { get; set; } [Required] [EmailAddress] [Display(Name = "Email")] public string Email { get; set; } [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "Confirm password")] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } } 
  • AK Yes, this is also not a bad option for withdrawal, but I wanted a little different. I just wanted to bring 2 different grids in a row. The first is a list of all programs, and the second is all users, with the name of the program for each user. THOSE. roughly speaking in the first grid of the Prog model and in the second grid of the User model. And I would like it to be like this, if I call the Users controller, then only the tablet with users will be rendered, and if the program controller is displayed, then both tablets will be drawn. That's what partial view for. So you can do? - Andrei
  • From my implementation, what I described, I just tried to pass a collection of user models to the parshial view with the help of my view of the bug, but this is impossible. That's why I ask how you can implement, thanks in advance. - Andrei
  • AK everything turned out, with the help of ViewData I transmitted, now I will change the code for the one with which everything worked as I wanted, but please do not erase your answer, I will accept it, let it remain, also a useful option. True, the last column went a little bit for some reason, but I’ll sort it out with the markup :) - Andrei
  • AK added everything. - Andrei