Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

ASP.NET Core view components

Suggested Videos
Part 21 - ASP.NET Core razor pages client side validation | Text | Slides
Part 22 - Delete operation in asp.net core razor pages | Text | Slides
Part 23 - Partial views in asp.net core | Text | Slides

In this video we will discuss View Components in ASP.NET core with example.

View component example


In addition to page specific content, we want to display the following Employee Head Count Summary on several pages in our application. 


asp.net core view component example

Since, we want to display the Employee Head Count Summary on several pages, it makes sense to create a reusable component. 

What we do not want to do is include the code on each page. This approach duplicates code. 

We can't use a partial view either, because a partial view cannot have it's own data access logic. It depends on the data passed from the parent view or razor page. We do not want to include the code that retrieves data on each page. This is again code duplication. We want something that can retrieve data independently and render. View Component is a perfect choice for this.

View Components folder

Create View Components folder, in the root project directory. We will place all our view components in this folder. Add a new class file with name - HeadCountViewComponent.cs. Copy and paste the following code.

using Microsoft.AspNetCore.Mvc;
using RazorPagesTutorial.Services;

namespace RazorPagesTutorial.ViewComponents
{
    public class HeadCountViewComponent : ViewComponent
    {
        private readonly IEmployeeRepository employeeRepository;

        public HeadCountViewComponent(IEmployeeRepository employeeRepository)
        {
            this.employeeRepository = employeeRepository;
        }

        public IViewComponentResult Invoke()
        {
            var result = employeeRepository.EmployeeCountByDept();
            return View(result);
        }
    }
}

View component class
  1. View component class name ends with the suffix ViewComponent
  2. It inherits from the ViewComponent base class
  3. It supports dependency injection, just like a razor page or an MVC controller
  4. A view component does not directly respond to an HTTP request. It is usually invoked and consumed by a razor page, layout view or an MVC view.
  5. When a view component is invoked, it calls the Invoke method.
  6. Inovke() method returns IViewComponentResult.
  7. Use InvokeAsync() method, if you want to call the View Component asynchronously.
  8. View Component follows the MVC design pattern. It initialises a model and passes it to a view by calling the View method.
  9. Though it follows the MVC approach, it can be used both in an MVC project and a razor pages project.
View Component view discovery

ASP.NET Core looks for the view in the following locations

Razor pages project
  • /Pages/Shared/Components/{View Component Name}/{View Name}
MVC project
  • /Views/{Controller Name}/Components/{View Component Name}/{View Name}
  • /Views/Shared/Components/{View Component Name}/{View Name}
Create view component view file
  1. In the Shared folder, create Components folder. 
  2. In the Components folder, create a folder with the same name as the View Component. Our view component name is HeadCountViewComponent. So create a folder with name HeadCount. The suffix ViewComponent is not required.
  3. In this folder create a file with name default.cshtml
At this point, the folder structure should look as shown below.

viewcomponent folder structure

Copy and paste the following code in default.cshtml

@model IEnumerable<DeptHeadCount>

<h3>Employee Head Count Summary</h3>

<table class="table table-bordered">
    <thead class="thead-light">
        <tr>
            <th>Department</th>
            <th>Head Count</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var deptHeadCount in Model)
        {
            <tr>
                <td>@deptHeadCount.Department</td>
                <td>@deptHeadCount.Count</td>
            </tr>
        }
    </tbody>
</table>

Rendering view component

Use Component.InvokeAsync to invoke the view component. We want to render it from Details razor page. So include the following code on Details.cshtml page.

@await Component.InvokeAsync("HeadCount")

Supporting classes

DeptHeadCount.cs in Models project

namespace RazorPagesTutorial.Models
{
    public class DeptHeadCount
    {
        public Dept Department { get; set; }
        public int Count { get; set; }
    }
}

IEmployeeRepository.cs in Models project

namespace RazorPagesTutorial.Services
{
    public interface IEmployeeRepository
    {
        // Other methods
        IEnumerable<DeptHeadCount> EmployeeCountByDept();
    }
}

MockEmployeeRepository.cs in Models project

namespace RazorPagesTutorial.Services
{
    public class MockEmployeeRepository : IEmployeeRepository
    {
        private List<Employee> _employeeList;

        public MockEmployeeRepository()
        {
            _employeeList = new List<Employee>()
            {
                new Employee() { Id = 1, Name = "Mary", Department = Dept.HR,
                    Email = "mary@pragimtech.com", PhotoPath="mary.png" },
                new Employee() { Id = 2, Name = "John", Department = Dept.IT,
                    Email = "john@pragimtech.com", PhotoPath="john.png" },
                new Employee() { Id = 3, Name = "Sara", Department = Dept.IT,
                    Email = "sara@pragimtech.com", PhotoPath="sara.png" },
                new Employee() { Id = 4, Name = "David", Department = Dept.Payroll,
                    Email = "david@pragimtech.com" },
            };
        }

        public IEnumerable<DeptHeadCount> EmployeeCountByDept()
        {
            return _employeeList.GroupBy(e => e.Department)
                            .Select(g => new DeptHeadCount()
                            {
                                Department = g.Key.Value,
                                Count = g.Count()
                            }).ToList();
        }
    }
}

asp.net core tutorial for beginners

2 comments:

  1. We greatly appreciate your effort, I have implemented ViewComponent and the problem is how to handle postbacks like grid event (sort, pagination). Can you please suggest me best approach?

    ReplyDelete
  2. Getting error in default.cshtml
    @model IEnumerable
    The type or namespace name 'DeptHeadCount' could not be found (are you missing a using directive or an assembly reference?)

    ReplyDelete

It would be great if you can help share these free resources