How do you access multiple class models in the same view without an aggregate class model?

CyberCoder11 1 Reputation point
2022-09-20T20:35:07.363+00:00

How do you access data from multiple class models in the same view without creating a clunky aggregated view model?

Example:

User Class Model:

public class User  
{  
    new public int ID { get; set; }  

    public string FirstName { get; set; } = string.Empty;  

    public string LastName { get; set; } = string.Empty;  
 }  

Class Model #2:

public class Company  
{  
    new public int ID { get; set; }  

    public string CompanyName { get; set; } = string.Empty;  

    public string CompanyType { get; set; } = string.Empty;  
 }  

Razor View:

@Anonymous
@默 CyberCoder.Pages.Users.IndexModel

<h1>Random User: @默 .User.First().FirstName </h1>
<h1>Random Company: @默 .First().CompanyName </h1>

I understand that the model declared in the Razor View is the Users.IndexModel. However, I don't understand how to access multiple classes in the same view and I would like to.

Online anecdotal advice states that you must create an overarching class that contains all the class models you want to display but this can create issues. For example, I do want a separate User class model for use elsewhere. However, I would like to be able to add Users to the Company class model (Users belong to a Company but can also be entirely separate).

It seems clunky to do the following:

public class Multiview  
{  
    new public int ID { get; set; }  

    public string FirstName { get; set; } = string.Empty;  

    public string LastName { get; set; } = string.Empty;  

    new List<User> Users = new List<User>;  
    new List<Company> Company= new List<User>;  

   etc.............  
 }  

Creating the above MultiView class seems fine and dandy until you realize that there could be some serious conflicts when a User or Company class object hits the database by itself vs. a User or Company class object that is created as a List object of the MultiView class.

Note: Minor syntax issues abound but the general idea/question is what I'm going for.
Note2: I am open to ViewData being a solution to this problem as well but it would still require you to haphazardly use ViewData in a Razor View that already has at least one defined model object without doing a series of convoluted partials.

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,157 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Michael Taylor 47,966 Reputation points
    2022-09-20T21:19:24.71+00:00

    You only get 1 type for Model. There is no changing that. The correct solution is to create a model that contains the data the view needs. That is the very essences of MVC. This is not where OOP design comes in. Creating models that are shared across views or use inheritance is an OOP. A view shouldn't know or care about the underlying data structure. All it wants is the data and that should ideally be as flat as possible. So aggregation is the best choice here. Create a MyViewModel that contains the 2 models you want the view to use. It is simple, it solves the problem and it has no impact on any other areas of the code.

       public class UsersAndCompany  
       {  
          public User User { get; set; }  
          public Company Company { get; set; }  
       }  
    

    Then your view can use either subset of data to build its UI. Other views can use one or the other or both as they see fit as well. Note that if there is a relationship between User and Company then you should ideally relate the models together anyway. Be careful about trying to use the database structure as the representation that the view uses. If you do that then you end up with a view that changes when the database changes. The view should get all the data it needs in a simple format irrelevant of how it is stored in the backend.

    In special cases where you need to pass extra data to a view (such as lookup values or whatnot) you can also use ViewBag to store data. But this should be reserved for data that sits outside the "model" that is being displayed. It makes the view harder to use and won't survive roundtrips to the server.

    Yet another option is to have your Razor code make a call to your backend service and store that into a temp variable. That code runs in the context of the view and therefore can get data that the view needs. This also is not recommended because it makes the view harder to use and it doesn't work with DI. But in a pinch it could be done.

    0 comments No comments