<< Back to Blog

29 JUNE 2017

.NET Core: Using View-Component to render dynamic page content

Sometimes it is necessary to render a piece of dynamic content across multiple pages on a site, e.g. a Company Name in the navbar. To get this information you may need to make a database call, and to do that there are a couple of options - one of which is a View Component.

What to avoid. We could update every controller (or Base controller) to override the ‘OnActionExecuting’ method and fetch our data to return in a ViewBag item to every page. The issue with this is that the base controller does not have D.I so you need to pass DbContext down from every controller. Basically, avoid this, and use below ‘View Component’ option.

ASP.Net Core introduces View Components. These are are similar to partial views with more power. View components don’t use model binding, and only depend on the data you provide when calling into it. A view component:

  • Renders a chunk rather than a whole response.
  • Includes the same separation-of-concerns and testability benefits found between a controller and view.
  • Can have parameters and business logic.
  • Is typically invoked from a layout page.

View components are intended anywhere you have reusable rendering logic that is too complex for a partial view, such as:

  • Dynamic navigation menus

###Usage

  1. In Views/Shared, add a ‘Components’ folder.
  2. Add classes in here with names always ending in ‘ViewComponent.cs’. E.g. CompanyNameViewComponent.cs.
  3. Each View Component should have a constructor, an InvokeAsync() method, and inherit from ViewComponent.
public class CompanyNameViewComponent : ViewComponent
{
    private readonly ApplicationDbContext _dbContext
    private readonly UserManager<ApplicationUser> _userManager

    public CompanyNameViewComponent(ApplicationDbContext dbContext, UserManager<ApplicationUser> userManager)
    {
        _dbContext = dbContext
        _userManager = userManager
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        string companyName = String.Empty
        var user = await _userManager.GetUserAsync(HttpContext.User)
        var userFull = _dbContext.Users.Where(x => x.Id == user.Id).FirstOrDefault()
        if (userFull != null)
        {
            companyName = userFull.CompanyName
        }

        return View("CompanyName", companyName)
    } 
}
  1. Then add a view to Views/Shared/Components/CompanyName/CompanyName.cshtml
@model string

@if (Model != String.Empty)
{
    <li class="nav-primary__item nav-primary__item--right">
        <div class="">@Model</div>
    </li>
}
  1. To call the component from the _Layout page add the following line.
@await Component.InvokeAsync("CompanyName")

// You can also add parameters and add these to InvokeAsync(int maxNum) to use
@await Component.InvokeAsync("CompanyName", { maxNum = 4 })