Back to: ASP.NET Core Tutorials For Beginners and Professionals
View Component Tag Helper in ASP.NET Core MVC
In this article, I will discuss the View Component Tag Helper in ASP.NET Core MVC Application with Examples. Please read our previous article discussing the Custom Tag Helper in ASP.NET Core Applications.
What is a View Component in ASP.NET Core MVC?
A View Component in ASP.NET Core MVC is a reusable component that helps to build a portion of a view’s UI, similar to a partial view but with more flexibility. View Components encapsulating the rendering logic that can be reused across different parts of an application. Unlike partial views that only include rendering logic, View Components can have their own business logic and data retrieval mechanism. A View Component typically consists of:
- A Class: This class handles the data fetching and business logic. This class inherits from ViewComponent and includes an Invoke or InvokeAsync method that performs the rendering logic. It returns a ViewComponentResult, typically returning a view.
- A View: The view associated with the View Component renders the output. It is usually stored in the Views/Shared/Components/{ViewComponentName}/Default.cshtml path, where {ViewComponentName} is the name of the View Component class.
View Components are useful for creating widget-like components in your application, such as a dynamic navigation bar, shopping cart, login panel, etc., that need to appear on multiple pages or require their own complex processing logic and data access.
What is a View Component Tag Helper in ASP.NET Core MVC?
The View Component Tag Helper in ASP.NET Core MVC is a built-in Tag Helper that allows us to invoke a View Component from within a Razor view using HTML-like syntax. This provides a cleaner and more readable way to invoke a View Component in a Razor view rather than using the traditional method of invoking the component using the HTML Helper method such as Component.InvokeAsync().
The tag helper syntax for invoking a View Component is similar to HTML tags, and it can include attributes passed to the View Component. The Tag Helper to invoke the View Components uses the syntax: <vc:[ViewComponentName]></vc:[ViewComponentName]>
For example, if we have a View Component named LatestNews, we could invoke it like this: <vc:latest-news></vc:latest-news>. Here, vc is a prefix for the tag helper, and latest-news is the name of the View Component.
View Component Tag Helper Real-Time Example in ASP.NET Core MVC
Let’s create a real-time ASP.NET Core MVC application using View Components and View Component Tag Helpers to build a Dynamic Navigation Bar and Shopping Cart. We will use Bootstrap for styling to ensure the application looks professional. Let us proceed and implement this example step by step. First, create a new ASP.NET Core Application named ViewComponentDemo using the Model View Controller Project template.
Creating Models
Next, we will create three models: Product, CartItem, and MenuItem. You can create a separate class file for each model. But for simplicity, we create a single class file named ViewComponentModel.cs within the Models folder and then copy and paste the following code.
namespace ViewComponentDemo.Models { public class Product { public int Id { get; set; } public string Name { get; set; } public string ProductImage { get; set; } public string Description { get; set; } public decimal Price { get; set; } } public class CartItem { public Product Product { get; set; } public int Quantity { get; set; } } public class MenuItem { public string Text { get; set; } public string Action { get; set; } public string Controller { get; set; } } }
Create Services to Provide Dummy Data
Next, we will create services that return dummy data for Product and Cart. We will create the services inside the Services folder. So, first, create a folder named Services.
Services/ProductService.cs
Create a class file named ProductService.cs within the Services folder, and then copy and paste the following code:
using ViewComponentDemo.Models; namespace ViewComponentDemo.Services { public class ProductService { private List<Product> _products = new List<Product> { new Product { Id = 1, Name = "Laptop", Price = 1000, Description = "A powerful laptop for professionals Developers", ProductImage = "https://dummyimage.com/600x400/000/fff&text=Laptop" }, new Product { Id = 2, Name = "Smartphone", Price = 500, Description = "Latest smartphone with cutting-edge features", ProductImage = "https://dummyimage.com/600x400/000/fff&text=Smartphone" }, new Product { Id = 3, Name = "Headphones", Price = 1500, Description = "Noise-cancelling over-ear headphones good for health", ProductImage = "https://dummyimage.com/600x400/000/fff&text=Headphones" } }; public IEnumerable<Product> GetAllProducts() { return _products; } } }
Services/CartService.cs
Create a class file named CartService.cs within the Services folder, and then copy and paste the following code:
using ViewComponentDemo.Models; namespace ViewComponentDemo.Services { public class CartService { private static List<CartItem> _cartItems = new List<CartItem>(); public IEnumerable<CartItem> GetCartItems() { return _cartItems; } public void AddToCart(Product product, int quantity) { var existingItem = _cartItems.FirstOrDefault(c => c.Product.Id == product.Id); if (existingItem != null) { existingItem.Quantity += quantity; } else { _cartItems.Add(new CartItem { Product = product, Quantity = quantity }); } } } }
Register the Services:
Next, we need to register the services into the dependency injection container. So, please add the following two statements to the Program class file:
builder.Services.AddSingleton<ProductService>();
builder.Services.AddSingleton<CartService>();
Modify Home Controller
The Home Controller is created by default when we create the ASP.NET Core project using the Model View Controller template. So, modify the HomeController as follows:
using Microsoft.AspNetCore.Mvc; using ViewComponentDemo.Services; namespace ViewComponentDemo.Controllers { public class HomeController : Controller { private readonly ProductService _productService; private readonly CartService _cartService; public HomeController(ProductService productService, CartService cartService) { _productService = productService; _cartService = cartService; } public IActionResult Index() { var products = _productService.GetAllProducts(); return View(products); } public IActionResult AddToCart(int id) { var product = _productService.GetAllProducts().FirstOrDefault(p => p.Id == id); if (product != null) { _cartService.AddToCart(product, 1); } return RedirectToAction("Index"); } public IActionResult Cart() { var cartItems = _cartService.GetCartItems(); return View(cartItems); } } }
Creating View Components
Next, we need to add the View Components. View Components are classes inherited from the ViewComponent class, and the class name must end with ViewComponent. We are going to create all the View Components inside the ViewComponents folder. So, first, add a folder named ViewComponents to the project root directory.
NavigationBarViewComponent
Create a class file named NavigationBarViewComponent.cs within the ViewComponents folder, and then copy and paste the following code. This View Component will generate a dynamic navigation bar.
using Microsoft.AspNetCore.Mvc; using ViewComponentDemo.Models; namespace ViewComponentDemo.ViewComponents { // Defining the View Component class named 'NavigationBarViewComponent' that inherits from the 'ViewComponent' base class. public class NavigationBarViewComponent : ViewComponent { // The Invoke method is the entry point of the View Component. // It is responsible for generating the view. // ASP.NET Core will automatically call this method when the View Component is used in a view. public IViewComponentResult Invoke() { // Creating a list of MenuItem objects representing the navigation bar menu items. // These items are hardcoded, but in a real application, this data could be fetched from a database, API, or configuration. var menuItems = new List<MenuItem> { // Adding a menu item for the "Home" page. The Action is "Index", and the Controller is "Home". new MenuItem { Text = "Home", Action = "Index", Controller = "Home" }, // Adding a menu item for the "Cart" page. The Action is "Cart", and the Controller is "Home". new MenuItem { Text = "Cart", Action = "Cart", Controller = "Home" }, // Adding a menu item for the "Contact" page. The Action is "Contact", and the Controller is "Home". new MenuItem { Text = "Contact", Action = "Contact", Controller = "Home" } }; // Returning the view for the View Component and passing the 'menuItems' list as the model. // The view will use this data to render the navigation bar in the UI. return View(menuItems); } } }
Next, we need to create a View for the Navigation Bar View Component. It should be created inside the Views/Shared/Components/NavigationBar/ folder, and the view name should be Default.cshtml. So, create a view named Default.cshtml within the Views/Shared/Components/NavigationBar/ folder and then copy and paste the following code.
<!-- Views/Shared/Components/NavigationBar/Default.cshtml --> @model List<MenuItem> <nav class="navbar navbar-expand-lg navbar-light bg-light shadow-sm"> <div class="container-fluid"> <a class="navbar-brand" href="#">My Shop</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav ms-auto"> @foreach (var menuItem in Model) { <li class="nav-item"> <a class="nav-link active" href="@Url.Action(menuItem.Action, menuItem.Controller)">@menuItem.Text</a> </li> } </ul> </div> </div> </nav>
ShoppingCartViewComponent
Create a class file named ShoppingCartViewComponent.cs within the ViewComponents folder, and then copy and paste the following code:
using Microsoft.AspNetCore.Mvc; using ViewComponentDemo.Services; namespace ViewComponentDemo.ViewComponents { // Defining a ViewComponent class named 'ShoppingCartViewComponent' that inherits from the 'ViewComponent' base class. public class ShoppingCartViewComponent : ViewComponent { // Declaring a private readonly field of type 'CartService' to store the injected service for accessing cart-related data. private readonly CartService _cartService; // Constructor for the ShoppingCartViewComponent class that takes an instance of 'CartService' as a parameter. // ASP.NET Core will use Dependency Injection to provide an instance of CartService when creating this ViewComponent. public ShoppingCartViewComponent(CartService cartService) { // Storing the injected CartService instance in the private field '_cartService' to access cart data within the class. _cartService = cartService; } // The Invoke method is the entry point of the ViewComponent. ASP.NET Core automatically calls this method when the ViewComponent is used in a view. public IViewComponentResult Invoke() { // Using the CartService instance to retrieve the list of items currently in the shopping cart. var cartItems = _cartService.GetCartItems(); // Returning the view for the ShoppingCartViewComponent, passing the 'cartItems' list as the model. // The view will use this data to render the shopping cart items in the UI. return View(cartItems); } } }
Next, we need to create a View for the Shopping Cart Component. It should be created inside the Views/Shared/Components/ShoppingCart/ folder, and the view name should be Default.cshtml. So, create a view named Default.cshtml within the Views/Shared/Components/ShoppingCart/ folder, then copy and paste the following code.
@model List<CartItem> @{ // Calculate the total amount decimal totalAmount = Model.Sum(item => item.Quantity * item.Product.Price); } @if (Model == null || !Model.Any()) { <div class="alert alert-warning text-center" role="alert"> <h4 class="alert-heading">Your Cart is Empty!</h4> <p>It seems like you haven't added any items to your cart yet.</p> <hr> <a href="@Url.Action("Index", "Home")" class="btn btn-primary">Continue Shopping</a> </div> } else { <div class="card shadow-lg mb-4"> <div class="card-header bg-dark text-white d-flex justify-content-between align-items-center"> <h5 class="mb-0">Shopping Cart</h5> <span class="badge bg-light text-dark fs-4">Total Items: @Model.Count</span> </div> <ul class="list-group list-group-flush"> @foreach (var item in Model) { <li class="list-group-item"> <div class="row align-items-center"> <div class="col-md-2"> <img src="@item.Product.ProductImage" alt="@item.Product.Name" class="img-fluid rounded border" style="width: 150px; height: 100px; object-fit: cover;"> </div> <div class="col-md-6"> <h6 class="mb-1">@item.Product.Name</h6> <p class="text-muted small mb-1">@item.Product.Description</p> <p class="mb-0 text-muted">Quantity: @item.Quantity</p> </div> <div class="col-md-4 text-end"> <span class="badge bg-success fs-6 p-2">$@item.Quantity * @item.Product.Price</span> <br /> <a href="#" class="btn btn-outline-danger btn-sm mt-2">Remove</a> </div> </div> </li> } </ul> <div class="card-footer d-flex justify-content-between align-items-center"> <div> <strong>Total Amount: </strong><span class="text-success fs-5">$@totalAmount</span> </div> <div> <a href="@Url.Action("Index", "Home")" class="btn btn-secondary btn-lg">Continue Shopping</a> <a href="#" class="btn btn-primary btn-lg">Proceed to Checkout</a> </div> </div> </div> }
Register the View Component:
Next, we need to add the View Component to the Razor view or globally to all views by adding @addTagHelper *, YourAssemblyName in the _ViewImports.cshtml file. So, modify the _ViewImports.cshtml as follows. Please replace ViewComponentDemo with the name of your assembly (i.e., the Project name).
@using ViewComponentDemo @using ViewComponentDemo.Models @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, ViewComponentDemo
Modify the Index View of the Home Controller
Modify the Index.cshtml view as follows, which you can find inside the Views/Home/ folder:
@model List<Product> @{ ViewData["Title"] = "Home"; } <h2 class="mb-4">Products</h2> <div class="row"> @foreach (var product in Model) { <div class="col-md-4 mb-4"> <div class="card h-100 shadow-sm"> <img class="card-img-top" src="@product.ProductImage" alt="@product.Name"> <div class="card-body"> <h5 class="card-title text-center">@product.Name</h5> <p class="card-text">@product.Description</p> <p class="card-text text-primary"><strong>Price: $@product.Price</strong></p> </div> <div class="card-footer text-center"> <a asp-action="AddToCart" asp-controller="Home" asp-route-id="@product.Id" class="btn btn-success btn-block">Add to Cart</a> </div> </div> </div> } </div>
Adding Cart.cshtml View:
Next, create a view named Cart.cshtml within the Views/Home folder and then copy and paste the following code. Here, we are calling the Shopping Card View Component using Tag helper.
@{ ViewData["Title"] = "Shopping Cart"; } <h2 class="mb-4">Shopping Cart</h2> <vc:shopping-cart></vc:shopping-cart>
Modify the Layout file:
Finally, modify the _Layout file as follows: Here, we call the navigation bar view component using Tag helper.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>@ViewData["Title"] - My Shop</title> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" /> <link rel="stylesheet" href="~/css/site.css" /> </head> <body> <header> <vc:navigation-bar></vc:navigation-bar> </header> <main role="main" class="container mt-3"> @RenderBody() </main> <footer class="footer mt-auto py-3 bg-light"> <div class="container"> <span class="text-muted">© 2024 My Shop</span> </div> </footer> <!-- JavaScript and dependencies --> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> <script src="~/js/site.js"></script> </body> </html>
That’s it. Run the application and test the functionalities; it should work as expected.
This should give you a basic real-time application using ASP.NET Core MVC with View Components and View Component Tag Helpers. It includes a dynamic navigation bar and shopping cart, all styled using Bootstrap. The application uses dummy data and demonstrates how to create reusable UI components with View Components and how to use them in Razor views.
In the next article, I will discuss Cache Tag Helper in ASP.NET Core MVC with Examples. In this article, I try to explain View Component Tag Helper in ASP.NET Core MVC Application with examples. I hope you enjoy this View Component Tag Helper in ASP.NET Core article.