Thursday, May 16, 2019

Creating a ViewModel object and bind it to the View

In the previous post we created a custom controller and we developed our own view and it worked. There is one think to note in that sample, the controller was passing a list of Employee object will all the properties, but the view was displaying only specific properties. Though this works it’s not efficient while displaying larger lists, we end up fetching way too much data from the database but not using it. To avoid this we have to create a custom ViewModel object with only properties used in the view. In this sample we will modify the previous example to use a ViewModel object.

First create another folder inside the Models folder, name it ViewModel we will create all our ViewModel objects inside this folder. Next create a class EmployeeSummary.cs in this folder as follows.

namespace HelloMVC.Models.ViewModel
{
    public class EmployeeSummary
    {
        public EmployeeSummary(int _id, string _name, int _age, string _phone)
        {
            EmployeeId = _id;
            Name = _name;
            Age = _age;
            Phone = _phone;
        }
        public int EmployeeId { get; set; }
        public string Name { get; set; }
        public int? Age { get; set; }
        public string Phone { get; set; }
    }
}

Next we will modify our controller’s Action method to get only the required columns from the DB by customizing the EF Core query, and create a list of EmployeeSummary model object instead of the Employees model which contains all the properties. The Controller method looks like this.

public async Task<IActionResult> Index()
{
    return View(await _context.Employee
        .Select(e => new EmployeeSummary(e.EmployeeId, e.Name, e.Age.Value, e.Phone))
        .ToListAsync());
}

Finally we will modify our View to use the EmployeeSummary model instead of the full Employee model object as follows.

@model IEnumerable<HelloMVC.Models.ViewModel.EmployeeSummary>
@{
    ViewData["Title"] = "Index";
}
<h1>Index</h1>

<div class="container">
    <div class="row">
        <div class="col-md-2">Id</div>
        <div class="col-md-2">Name</div>
        <div class="col-md-2">Age</div>
        <div class="col-md-2">Phone</div>
        <div class="col-md-2">Actions</div>
    </div>
    @foreach (var item in Model)
    {
        <div class="row">
            <div class="col-md-2">@Html.DisplayFor(modelItem => item.EmployeeId)</div>
            <div class="col-md-2">@Html.DisplayFor(modelItem => item.Name)</div>
            <div class="col-md-2">@Html.DisplayFor(modelItem => item.Age)</div>
            <div class="col-md-2">@Html.DisplayFor(modelItem => item.Phone)</div>
            <div class="col-md-2"></div>
        </div>
    }
</div>

Build and run the project, the output for this sample will be the same as the pervious sample, but more efficient since we fetch only limited columns from the DB which are required to be displayed in the view.

Search Flipkart Products:
Flipkart.com

No comments: