How To Create ViewComponent in ASP.NET CORE

View components are similar to partial views, a view component is a self-contained block of reusable code that can be used in the entire application and also can be unit tested.

In ASP.NET MVC we had Child Action ([ChildActionOnly]) attribute which we use to apply on action method which prevent action method directly invoking from the browser but which we can invoke from View using @Html.Action helper.

The [ChildActionOnly]) attribute is no more in ASP.NET CORE we can use View components which has similar features but it does not require action method to declared.

View component is similar to the mini controller where we can inject dependency write your business logic access database and return View as a response.

  • View component directly cannot handle Http Request.
  • Fully supports constructor dependency injection
  • Doesn’t take part in the controller lifecycle, which means you can’t use filters in a view component.

Reference:- https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-2.2

In Demo, we are going to render Menu which we will bring from the database.

  1. Creating ASP.NET Core Application
  2. Setting up Database and Table
  3. Adding Entity Framework Core package from NuGet
  4. Configuring Connection string in appsettings.json
  5. Creating a Menu Model
  6. Adding DatabaseContext Class and inheriting with DbContext class
  7. Registering Dependency injection AddDbContext
  8. ConfigureServices Method in Startup Class
  9.  Adding MenuViewComponent Class and Inheriting with ViewComponent Class
  10.  Injecting ‘DatabaseContext‘ Dependency in MenuViewComponent
  11.  Sending Model to View
  12.  Creating Default.cshtml View for MenuViewComponent
  13.  Calling MenuViewComponent on View
  14.  Calling the View component directly from the controller

Creating ASP.NET Core Application

We are going to create ASP.NET Core Web Application for that we are going to choose ‘ASP.NET Core Web Application‘ template.

Next, we are going to set Project Name ‘WebApplication9‘ and location and in last part, we are going to choose .Net Core framework and ASP.NET Core Version 3.0 as framework for application and few advance settings for such as configuring https and enabling docker we are not going to enable both of settings for this project.

Now finally click on create button to create a project.

After creating a project, we are going to run this project.

Setting up Database and Table
We have created a database with Name Sample2 and then we have added product table in it.
Below is Table structure along with a script to create a table.

Adding Entity Framework Core package from NuGet

In this part, we are going to learn how to add Entity Framework Core package to project from NuGet package manager.

For adding a package from NuGet right-click on Main project “WebApplication9” and from the menu select Manage NuGet Packages. As you select it a New dialog of NuGet Package Manager with search box will pop up.

In choose browse tab and search “Microsoft.EntityFrameworkCore.SqlServer” and choose version 3.0.0 the latest version of “Microsoft.EntityFrameworkCore.SqlServer ” is in the preview that why we have chosen them, finally click on the install button for adding the package.

After adding Microsoft.EntityFrameworkCore.SqlServer to project next we are going to Configuring Connection string in appsettings.json.

Configuring Connection string in appsettings.json

Here in ASP.NET core, we don’t have web.config file which was there in the older version of ASP.NET and ASP.NET MVC here we have appsettings.json file where we are going to keep application-level settings and this file is Json based.

appsettings.json file

In this file, we have added ConnectionStrings section inside that we have added “DatabaseConnection” key and other is value.

Notice: – here I am using SQL based authentication for database connection that why I have added User Id and password of SQL server.

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DatabaseConnection": "Data Source=SAI-PC\\SQLEXPRESS; initial catalog=Sample3; user id=sa; password=Pass"
  }
}

Next, after adding connection string we are going to add Model Menu in Models folder.

Adding the Menu Model

using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace WebApplication9.Models
{
    [Table("Menu")]
    public class Menu
    {
        [Key]
        public int MenuId { get; set; }
        public string MenuName { get; set; }
        public bool? IsActive { get; set; }
        public string ControllerName { get; set; }
        public string ActionName { get; set; }
    }
}

Next, after adding Menu Model we are going to add DatabaseContext Class and inheriting with DbContext class.

Adding DatabaseContext Class and inheriting with DbContext class

We are going to add DatabaseContext class which will inherit DbContext class and DatabaseContext constructor accepts the DbContextOptions as an argument. The DbContextOptions carries the configuration information needed to configure the DbContext.

After adding DatabaseContext class we have defined DbSet entity for Menu Model.

using Microsoft.EntityFrameworkCore;

namespace WebApplication9.Models
{
    public class DatabaseContext : DbContext
    {
        public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
        {
        }

        public DbSet<Menu> Menu { get; set; }
    }
}

After Configuring DatabaseContext class next we are going Register DatabaseContext as a service.

Registering Dependency injection AddDbContext

In this part, we are going to register DatabaseContext class as a service for using it as dependency injection which will be available to the entire application.
We are going to register this service in ConfigureServices Method of startup class.
First, we need to read connection string from appsettings.json file to pass it to register service.

//Getting Connection String from appsettings.json
var connection = Configuration.GetConnectionString("DatabaseConnection");

Next, we are going to use AddDbContext extension method to register the DatabaseContext in the dependency injection container.

services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection));

Use a ROW_NUMBER() in queries instead of OFFSET/FETCH. This method is backwards-compatible to SQL Server 2005 then register below method.

services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection, b => b.UseRowNumberForPaging()));

ConfigureServices Method in Startup Class

public void ConfigureServices(IServiceCollection services)
{
    //Getting Connection String from Database
    var connection = Configuration.GetConnectionString("DatabaseConnection");

    services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection));
    // OR
    services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection, b => b.UseRowNumberForPaging()));

    services.AddControllersWithViews();
}

Now we can use DatabaseContext class as service for dependency injection in the entire application.

Adding MenuViewComponent Class and Inheriting with ViewComponent Class

In this part, we are going to add a new folder with the name “Components” in the Project to store all project Components.

Next, we are going to add a class with name “MenuViewComponent” in Components folder and then we are going to inherit with ViewComponent class after inheriting next we are going to add Method InvokeAsync inside MenuViewComponent class which will return View.

Next Step Decorating a MenuViewComponent class with the [ViewComponent] attribute and set its Name property to “MenuView“.

using Microsoft.AspNetCore.Mvc;

[ViewComponent(Name = "MenuView")]
namespace WebApplication9.Components
{
    public class MenuViewComponent : ViewComponent
    {
        public IViewComponentResult InvokeAsync()
        {
            return View();
        }
    }
}

Injecting “DatabaseContext” Dependency in MenuViewComponent

After adding Component next we are going to use constructor injection to access DatabaseContext class for accessing Menu Details from Database.

using Microsoft.AspNetCore.Mvc;
using WebApplication9.Models;

[ViewComponent(Name = "MenuView")]
namespace WebApplication9.Components
{
    public class MenuViewComponent : ViewComponent
    {
        private DatabaseContext _databaseContext;
        public MenuViewComponent(DatabaseContext databaseContext)
        {
            _databaseContext = databaseContext;
        }
        public IViewComponentResult InvokeAsync()
        {
            return View();
        }
    }
}

Sending Model to View

Next, we are going Return List of Menu Model to View.

using System.Linq;
using Microsoft.AspNetCore.Mvc;
using WebApplication9.Models;

[ViewComponent(Name = "MenuView")]
namespace WebApplication9.Components
{
    public class MenuViewComponent : ViewComponent
    {
        private readonly DatabaseContext _databaseContext;
        public MenuViewComponent(DatabaseContext databaseContext)
        {
            _databaseContext = databaseContext;
        }
        public IViewComponentResult InvokeAsync()
        {
            var listofMenu = (from menu in _databaseContext.Menu
                              where menu.IsActive == true
                              select menu).ToList();

            return View(listofMenu);
        }
    }
}

Next, we are going to add View.

Creating Default.cshtml View for MenuViewComponent

Component View is Search in Following locations

  • /Views/{Controller Name}/Components/{View Component Name}/{View Name}
  • /Views/Shared/Components/{View Component Name}/{View Name}

We are going to add View at this location
“/Views/Shared/Components/{View Component Name}/{View Name}”

For Adding View, we need to add Components folder inside “/Views/Shared” next in Components folder we are going to add another folder with Name of Component (“MenuViewComponent“) “MenuView“.

Inside “MenuView” we are going to add View with Name “Default.cshtml” as per conventions.

Note: – The default view name for a view component is Default, which means your view file will typically be named Default.cshtml.

Code Snippet inside Default.cshtml

In Default.cshtml View we are going to get Menu List which we are going to iterate to create Vertical Menu.

@model List<Menu>

<ul class="nav flex-column">
    @foreach (var menu in Model)
    {
     <li class="nav-item">
      <a class="nav-link" href="/@menu.ControllerName/@menu.ActionName">@menu.MenuName</a>
     </li>
    }
</ul>

After writing the logic for generating HTML Next, we are going to Calling this MenuViewComponent on View to Render for doing that we are first going to add a controller with Name “DemoController” which has Index action Method in it next we are going to Add “Index” View.

Calling MenuViewComponent on View

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    @await Component.InvokeAsync("MenuView")
</body>
</html>

Output

Finally, we are going to call Demo Controller and Index Action Method to See MenuViewComponent rendered on Index View.

Calling the View component directly from the controller

using Microsoft.AspNetCore.Mvc;

namespace WebApplication9.Controllers
{
    public class DemoController : Controller
    {
        public IActionResult Index()
        {
            return ViewComponent("MenuView");
        }
    }
}

Output

By Saineshwar Bageri

I am Microsoft MVP | C# Corner MVP | Code Project MVP | FULL STACK .NET Developer and working on .Net Web Technology (Asp.net, Asp.net Core,.Net Core, C#, Sqlserver, MVC, Windows, Console Application, javascript, jquery, json, ORM Dapper) and also a freelance developer.