Can I have two view models in one controller?

I am having trouble understanding whether this is possible or not. I have stored procedures, view model classes, and one controller. Is it possible that I could add another class of the view model with another stored procedure in order to use one controller and display information from both stored procedures in one view?

This is my current model:

public class People { public class Jobs { public int jobID { get; set; } public string jobName { get; set; } } public class Names { public int userId{get;set} public string userName {get; set;} } } 
+6
source share
1 answer

Yes, it is quite possible. Just create a view model that contains properties that will be populated with your stored procedures, and then pass this to your view:

 public class PeopleViewModel { public List<Job> Jobs { get; set; } public List<Name> Names { get; set; } } 

Then the action method:

 public ActionResult Index() { var model = new PeopleViewModel(); model.Jobs = // ... fetch from database model.Names = // ... fetch from database return View(model); } 

Update for comments

As you said, Jobs and Names are collections, the model code that you showed will not solve your problem. Looks like this is what you really want:

 public class Job // Notice I've removed the pluralisation { public int jobID { get; set; } public string jobName { get; set; } } public class Name // Notice I've removed the pluralisation { public int userId { get; set; } public string userName { get; set; } } 

Your People class may now contain the following lists:

 public class People { public List<Job> Jobs { get; set; } public List<Name> Names { get; set; } } 

Now you can wrap this in a view model:

 public class PeopleViewModel { public People People { get; set; } } 

Then you will fill it out from your action:

 public ActionResult Index() { var model = new PeopleViewModel(); model.People = // ... fetch from database return View(model); } 

The fact is that if Jobs and Names not connected to each other, it makes no sense to deceive them in the People class. You simply do the following (as discussed above):

 public class PeopleViewModel { public List<Job> Jobs { get; set; } public List<Name> Names { get; set; } } 

Think of the presentation model as a way of representing just a piece of the data that you want to display in your view, and nothing more, nothing less. All of the code above determines what data you would like to see in this view. Since the properties on the view model are publicly available, you can populate them in the action of your controller using any method you use.

Second update

I think it would probably be useful to show you a complete example of how your views fit together. First, I will show you a quick and dirty way to access data in your view model, and then I will show you how to do the same with DisplayTemplates .

Quick and dirty approach

So, first suppose we have an action called Index as follows:

 public ActionResult Index() { var model = new PeopleViewModel(); model.Jobs = // ... fetch from database model.Names = // ... fetch from database return View(model); } 

Here Index :

 @model PeopleViewModel @foreach (var job in Model.Jobs) { @Html.DisplayFor(m => job.JobId) @Html.DisplayFor(m => job.JobName) } @foreach (var name in Model.Names) { @Html.DisplayFor(m => name.UserId) @Html.DisplayFor(m => name.UserName) } 

Notice how the view expects the PeopleViewModel instance, and it simply PeopleViewModel over each individual item in each collection, printing the contents. However, while this is great for very simple presentations, the logic of mixing with your HTML becomes a headache for maintenance with more complex views and larger projects. With that in mind, we can use DisplayTemplates instead.

Second approach - Using templates

The action in your controller remains unchanged. However, we need to make some other changes. We are working to turn the Index view into this:

 @model PeopleViewModel @Html.DisplayFor(m => m.Jobs) @Html.DisplayFor(m => m.Names) 

By calling Html.DisplayFor in this way, it will try to find a DisplayTemplate that matches the type of data that is being transmitted. In this case, the assistant is smart enough to know that we are passing the collection to him, and so he will look for a template that matches the type of data that the collection contains. This means that we need to create templates for the types Job and Name . To do this, follow these steps:

  • Create the DisplayTemplates folder inside the current view folder (for example, if your view is Home\Index.cshtml , create the Home\DisplayTemplates ).
  • Create a strongly typed view in this directory with a name that matches your model (i.e., in this case, you would make two types that would be called Job.cshtml and Name.cshtml respectively).

Now you can move all the display logic into these two templates. Therefore, they would look like this:

Job.cshtml

 @model Job @Html.DisplayFor(m => m.JobId) @Html.DisplayFor(m => m.JobName) 

Name.cshtml

 @model Name @Html.DisplayFor(m => m.UserId) @Html.DisplayFor(m => m.UserName) 

Hope this makes it a little easier.

+12
source

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


All Articles