Using ViewModels in ASP.Net MVC 5.0 applications
In this post I am going to create a hands on example, a sample ASP.Net MVC application where I will demonstrate the concept of ViewModels.
As we know MVC is a UI design pattern.
MVC is based on an architecture model that embraces the so called "seperation of concern pattern".
There are three main building blocks in the MVC pattern.The Controller orchestrates everything.When we have an HTTP request coming in, that request is routed to the Controller. The View talks to the Model. The Model has the data that the View needs to display.The View does not have much logic in them at all.
We design our business domain (after extracting our use cases from the specification document) by creating the appropriate classes in the Models folder.
The Controller handles all user interaction logic. The View contains all the user interface that the user will interact.
So if MVC is a separation of concerns pattern, why we need another concept like ViewModels.
In our ASP.Net MVC applications we need to pass data, or display data from more than one models.This is common task and we can use ViewModels to achieve that.
If you want find out more ways to pass multiple models to a view you can look at this post and this post.
With the ViewModels we can get data from multiple data models, get those entities and shape them as we need. Then the View will need to consume that single object which is our ViewModel.
Another example where we can use ViewModels is when we have presentation logic issues. In our model e.g Customer we can have a DateOfBirth property with the datatype DateTime.
Let's say in our View we need to display only the Age of the person. That would need some calculation, some logic. That logic needs to go to View. At this point we broke the separation of concerns principle. ViewModels can help us implement that logic, which is a presentation logic and does not belong to any other building blocks of MVC, Controller,View or Model.
As stated earlier I will create a sample ASP.Net MVC 5.0 application. I will use a database that I have already created and the EF database first paradigm to access the database.
I am going to need a database for this example. The database is called Projects. There are two tables, Project and Employee.
There are employees that belong to projects, one project has many employees. This is 1->N relationship between projects and employees.
You can download the script that will create the database and populate the tables here.
Make sure you run the script in an instance of SQL Server you have.
I will use Visual Studio 2015 Enterprise edition to create this sample application. You can use Visual Studio Express edition or Community edition.
1) I need to display data in my MVC application from both the Employee and Project tables.
Open your Visual Studio and create empty ASP.NET MVC application.
Click on File -> New Project -> Web -> ASP.NET web application.
From next window Select template Empty and from Add folders and core reference choose MVC.
Give it an appropriate name e.g ViewModels. Now you have in your Solution Explorer window the typical structure of an ASP.Net MVC application.
2) We need to install Entity Framework throgh Nuget Package Manager. Then we need to add an ADO.NET Entity Data Model.
Right click on Model folder and select Add inside that Select ADO.NET Entity Data Model. Follow the steps of the wizzard, connect to the database and include the two tables in your model.So the model will be generated from the database. You will see the two classes Project and Employee in your Model folder.
3) I am going to create a ViewModels folder. Inside that folder I will create a new class ProjectViewModel.
We will add properties from both out Models to ProjectViewModel class. I will take Name,Surname,Age,Role from Employee model and ProjectName from Project model.
The code for the ProjectViewModel class follows.
Snippet
public class ProjectViewModel
{
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public string Role { get; set; }
public string ProjectName { get; set; }
}
4) Now I am going to create a controller. I will create an empty controller.
To add a controller right click on Controllers Folder, select Add and then select Controller. After selecting controller a new Add Controller Dialog will popup.Name the controller ProjectEmployeesController, select Empty MVC Controller and click on Add button.
The code for the ProjectEmployeesController code follows
public class ProjectEmployeesController : Controller
{
// GET: ProjectEmployees
public ActionResult Index()
{
ProjectsEntities ctx = new ProjectsEntities();
List<ProjectViewModel> ProjectEmployeeslist = new List<ProjectViewModel>();
var datalist = (from proj in ctx.Projects
join emp in ctx.Employees on proj.ProjectId equals emp.ProjectId
select new {proj.ProjectName , emp.Name, emp.Surname, emp.Age, emp.Role}).ToList();
foreach (var item in datalist)
{
ProjectViewModel pvm = new ProjectViewModel();
pvm.ProjectName = item.ProjectName;
pvm.Name = item.Name;
pvm.Surname = item.Surname;
pvm.Age = item.Age;
pvm.Role = item.Role;
ProjectEmployeeslist.Add(pvm);
}
return View(ProjectEmployeeslist);
}
}
I create an instance of the DbContext class.
I then create a list object of type ProjectViewModel to hold the data from both the Project and Employee entities.
Then I query my model to get the data in the datalist. I iterate through datalist and store the values from the entities to the properties of the ProjectViewModel object pvm.
Finally I add the pvm object with all the values to the ProjectEmployeeslist object which can hold objects of type ProjectViewModel and then pass the model to the view.
5) Now we need to create the View to display the data from the model.Right click inside Index ActionResult Method and Select "Add View" to create the view template for our Index method. We are going to create a strongly typed view by selecting the Model class ProjectViewModel and we want to create a List. The scaffold mechanism will create our view that you can see below. As you can see below in the first line of the view I pass the ProjectViewModel ViewModel.
@model IEnumerable<ViewModels.ViewModels.ProjectViewModel>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Surname)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th>
@Html.DisplayNameFor(model => model.Role)
</th>
<th>
@Html.DisplayNameFor(model => model.ProjectName)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Surname)
</td>
<td>
@Html.DisplayFor(modelItem => item.Age)
</td>
<td>
@Html.DisplayFor(modelItem => item.Role)
</td>
<td>
@Html.DisplayFor(modelItem => item.ProjectName)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
6) Build and run your application. You will will see data from both entities appear in the View.
To recap ViewModels gives us the flexibility to shape data according to our business needs. We can add inside our ViewModels data that come from different entities or write presentation logic that does not belong to the View.
Hope it helps!!!