Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια

Dot Net Rules

Yes, to dance beneath the diamond sky with one hand waving free

Ιστορικό Δημοσιεύσεων

Ιούνιος 2016 - Δημοσιεύσεις

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 { getset; }
            public string Surname { getset; }
            public int Age { getset; }
            public string Role { getset; }
 
            public string ProjectName { getset; }
        }

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!!!

Using Jquery Ajax method in ASP.Net MVC

In this post I will use a simple ASP.Net 5.0 MVC application to implement a jQuery Ajax call to an ASP.Net MVC controller.

JQuery is not only about DOM manipulation and handling events on the client. It is very powerful when we want to manipulate HTML elements but also can talk with server side and instantiate 

In this example we will use the JQuery Ajax function to talk to an ASP.Net MVC controller and result JSONResult to the view. 

You can have a look in this post of mine where I talk about JQuery Ajax functions.

In this post I provide a more extended example on how to use JQuery Ajax functions.

I am going to create a sample application where I will have a simple dropdown which I will populate with data.

Every time there is a change in the DropDown control, there will be a JQuery Ajax call to the controller.

There are employees that belong to projects, one project has many employees. This is 1->N relationship between projects and employees.

I am going to need a database for this example. The database is called Projects. There are two tables, Project and Employee.

The dropdown control will have the project values and when the user selects different values (projects) the respective employees of the current project are loaded into a table.

I will use Visual Studio 2015 Ultimate edition to create this sample application. You can use Visual Studio Express edition or Community edition.

You can download the script here.

1) 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. Now you have in your Solution Explorer window the typical structure of an ASP.Net MVC application.

2) Now we need to create a model to represent the Employee entity

Right click on Models folder and select Add -> Class name it as Product -> click Ok.

Add below properties for Employee model.

public class Employee
{
       public int EmployeeID { get; set; }


       public string Name { get; set; }

      public string Surname { get; set; }

      public int Age { get; set; }

      public string Role { get; set; }


}

3) Now we need to add a controller in the Controllers folder. Right click on Controllers folder and select Add -> Controller.

Choose an Empty Controller. and click Add.

Name it as HomeController.

I will add a ShowProjects method in the HomeController.

public ActionResult ShowProjects()
{
List<SelectListItem> items = new List<SelectListItem>();

items.Add(new SelectListItem
{
Text = "Select Category",
Value = "0",
Selected = true
});

items.Add(new SelectListItem { Text = "E-shop", Value = "1" });

items.Add(new SelectListItem { Text = "Web Portal", Value = "2" });

items.Add(new SelectListItem { Text = "Blog", Value = "3" });

ViewBag.CategoryType = items;

return View();

}

As you can see I do not get the projects from the database. I only have 3 projects so I load them into a list and then add those items in the Category property of the ViewBag.

4) In the next step we need to add an MVC View to our project.

In this step you will add a MVC View to display Project and Employee details.

Open HomeController from Controllers folder -> Go to ShowProjects action method -> right click and select Add View.

It adds a View under Views -> Home folder with name ShowProjects.cshmtl.

We nee to add a DropDownList to display Projects and empty table to show employees depending on selected project.

The code follows


@{
ViewBag.Title = "ShowProjects";
}

<h2>Show Projects and their respective Employees</h2>

@using (Html.BeginForm("CategoryChosen", "Home", FormMethod.Get))


{
<table cellspacing="2" cellpadding="2">
<tr>
<td>
Category Type :
</td>
<td>
@Html.DropDownList("CategoryType")
</td>
</tr>
</table>

<br />

<div>
<table id="tblEmployees" class="tblEmployees">
<thead>
<tr>
<th align="left" class="employeeth">Employee ID</th>
<th align="left" class="employeeth">Name</th>
<th align="left" class="employeeth">Surname</th>
<th align="left" class="employeeth">Age</th>
<th align="left" class="employeeth">Role</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>

}

5) Add a styles.css file to your project.


.tblEmployees {
font-family: verdana,arial,sans-serif;
font-size: 11px;
color: #fff;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}

.employeeth {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #1aa33e;
}

.employeetd {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
color:#000;
}

In the _Layout.cshtml add a reference to the styles.css

 <link href="~/Content/styles.css" rel="stylesheet" />

6) Now we need to add another action on the HomeController controller.

Open HomeController controller and add an action method which accepts Project ID as input parameter, create list of employess whose ProjectID is equal to input parameter and return it as JSON result.

The action method and code follows.

public JsonResult GetEmployees(string id)
{
List<Employee> employees = new List<Employee>();

string query = string.Format("SELECT [EmployeeID], [Name], [Surname],[Age],[Role] " +
" FROM [Projects].[dbo].[Employee] WHERE ProjectID = {0}", id);

using (SqlConnection con = new SqlConnection("Data Source=FOFO-PC;Initial Catalog=Projects;Integrated Security=True"))
{
using (SqlCommand cmd = new SqlCommand(query, con))
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();

while (reader.Read())
{
employees.Add(
new Employee
{
EmployeeID = reader.GetInt32(0),
Name = reader.GetString(1),
Surname = reader.GetString(2),
Age = reader.GetInt32(3),
Role= reader.GetValue(4).ToString()

}
);
}
}
}

return Json(employees, JsonRequestBehavior.AllowGet);
}

The code is very simple. I do not use EF in this sample application. I am using simple ADO.Net to retrieve data from the database.

I am creating a list of employees list.

I create a variable that holds the SQL query.

I am using the SQLConnection object to open a connection to the database and then execute the query with the SQLCommand object.

I use the SQLDataReader object to create a reader object and populate it with values.

Finally I return the data in JSON format.

7) 

Νow we need to add code for CategoryType DropDownList change event. This will create AJAX call to MVC controller GetEmployees action method.

Below is the code which fires on change of DropDownList, create AJAX call with required details, make a call to GetEmployees controller action method, accepts JSON result and display as Table object.

There must be a reference to the JQuery library.

In the _Layout.cshtml add a reference to JQuery library.

   <script src="~/Scripts/jquery-1.10.2.min.js"></script>

<script type="text/javascript">

$(document).ready(function () {

$("#CategoryType").change(function () {

$("#tblEmployees tbody tr").remove();

$.ajax({

type: 'POST',

url: '@Url.Action("GetEmployees")',
dataType: 'json',
data: { id: $("#CategoryType").val() },
success: function (data) {
var items = '';
$.each(data, function (i, item) {

var rows = "<tr>"
+ "<td class='employeetd'>" + item.EmployeeID + "</td>"
+ "<td class='employeetd'>" + item.Name + "</td>"
+ "<td class='employeetd'>" + item.Surname + "</td>"
+ "<td class='employeetd'>" + item.Age + "</td>"
+ "<td class='employeetd'>" + item.Role + "</td>"
+ "</tr>";
$('#tblEmployees tbody').append(rows);
});

},
error: function (ex) {
var r = jQuery.parseJSON(response.responseText);
alert("Message: " + r.Message);
alert("StackTrace: " + r.StackTrace);
alert("ExceptionType: " + r.ExceptionType);
}
});
return false;
})
});

</script>

There is a post action to the GetEmployees action controller method, passing the CategoryTyepe value.

On success it displays JSON string send by action method, manipulate it and display product details on View.

On failure we get information about the error (Message, StackTrace and ExceptionType)

Go to http://localhost:21131/Home/ShowProjects  (you will have your own port number), select any value from CategoryType DropDownList. This will make an AJAX call and will the fill Employees table. Have a look at the picture below.

You can also see the JSON results returned by the controller after the Ajax call using the developer tools of any browser. I am using Chrome.

Have a look at the picture below.



Hope it helps!!!