📱 ASP.NET Core MVC Mobile Shop – Part 5: Making the Brand Menu Dynamic with ViewComponents

 


Part 5: Making the Brand Menu Dynamic with ViewComponents

In a real-world Mobile Shop Website, you don't want to hardcode your brand names (like Apple or Samsung) in the HTML. If you add a new brand to your database, it should automatically appear in your navigation menu.

To achieve this in ASP.NET Core MVC, we use a powerful feature called ViewComponents.

Step 1: Creating the BrandsMenuViewComponent

A ViewComponent is similar to a "mini-controller." It can execute logic and fetch data from the database without needing a full MVC action.

  1. Create a new folder in your project root named ViewComponents.

  2. Inside that folder, create a new class file named BrandsMenuViewComponent.cs.

  3. Paste the following code:


C# / ViewComponents/BrandsMenuViewComponent.cs

using Microsoft.AspNetCore.Mvc;
using MobileShop.Data;
using System.Linq;

namespace MobileShop.ViewComponents
{
    public class BrandsMenuViewComponent : ViewComponent
    {
        private readonly ApplicationDbContext _context;

        public BrandsMenuViewComponent(ApplicationDbContext context)
        {
            _context = context;
        }

        public IViewComponentResult Invoke()
        {
            // Fetching only active brands from the database
            var brands = _context.Brands
                                 .Where(b => b.IsActive)
                                 .OrderBy(b => b.Name)
                                 .ToList();

            return View(brands);
        }
    }
}

Detailed Technical Explanation

1. Why use ViewComponent instead of Partial View?

While Partial Views are great for rendering UI, they cannot easily fetch their own data. If you put a Brand list in a Partial View, you would have to pass that list from every single Controller in your app. ViewComponents solve this by being self-contained—they fetch their own data, making them perfect for Navbars and Sidebars.

2. Dependency Injection in ViewComponents

Just like our Controllers, we use the constructor to inject the ApplicationDbContext. This allows our component to communicate with the SQL database securely and efficiently.

3. The Invoke() Method

The Invoke method is the heart of the component.

  • LINQ Query: _context.Brands.Where(b => b.IsActive).ToList() ensures that if you temporarily disable a brand in your admin panel, it will instantly disappear from the public website menu.

  • Return View: This passes the list of brands to a specific View file (which we will create in the next step).

Step 2: Designing the ViewComponent UI (Default.cshtml)

Now that we have created the logic in the backend, we need to define how the brands will look in the browser. For ViewComponents, the location of the file is extremely important.

The Folder Structure: Why Shared/Components/?

In ASP.NET Core MVC, ViewComponents follow a strict naming convention. You must create the file in this exact path: Views/Shared/Components/BrandsMenu/Default.cshtml

Why this location?

  • Automatic Discovery: The MVC engine specifically looks in the Components folder for any file named Default.cshtml.

  • Global Access: By placing it in the Shared folder, we ensure that the Brand Menu can be called from any layout, page, or view throughout the entire website.


The Code: Views/Shared/Components/BrandsMenu/Default.cshtml

Razor / Views/Shared/Components/BrandsMenu/Default.cshtml

@model IEnumerable<MobileShop.Models.Brand>

<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">
        Brands
    </a>
    <ul class="dropdown-menu shadow">
        @foreach (var brand in Model)
        {
            <li>
                <a class="dropdown-item" 
                   asp-controller="Products" 
                   asp-action="Index" 
                   asp-route-brandId="@brand.Id">
                    @brand.Name.ToUpper()
                </a>
            </li>
        }

        <li><hr class="dropdown-divider"></li>
        <li>
            <a class="dropdown-item fw-bold text-primary" asp-controller="Products" asp-action="Index">
                View All
            </a>
        </li>
    </ul>
</li>

Detailed Step-by-Step Explanation

1. The Data Model (@model)

We use @model IEnumerable<Brand>. This tells the view to expect a collection of Brand objects from our BrandsMenuViewComponent. This strongly-typed approach prevents errors and enables IntelliSense while coding.

2. Dynamic Dropdown Generation

Instead of hardcoding "Apple" or "Samsung," we use a @foreach loop.

  • Automation: Every brand you mark as IsActive in your database will automatically create a new <li> entry here.

  • UI Consistency: Using @brand.Name.ToUpper() ensures that your menu looks uniform and professional, regardless of how the name was typed into the database.

3. Tag Helpers for Navigation

We use asp-route-brandId="@brand.Id". This is crucial for SEO and Routing. It creates a clean URL that tells the controller exactly which brand the user wants to see. This makes your "Mobile Shop" easy for Google to index.

4. Dropdown Divider

The <hr class="dropdown-divider"> is a standard Bootstrap class. It helps separate the dynamic list from the "View All" option, providing a better User Experience (UX).


How to call it in _Layout.cshtml?

To see this in action, you simply replace your old hardcoded Brand <li> in the Navbar with this single line:

@await Component.InvokeAsync("BrandsMenu")

This concludes the dynamic menu implementation! By following this pattern, you’ve made your website more scalable and professional.

Comments