Using ViewComponents in ASP.NET Core 2.0

While developing our new web application, we wanted to take a component-based approach and build up the user-interface from small, discreet UI components. So instead of having monolithic Razor Page containing many different controls, we thought it would be a far better design approach to develop the UI from smaller, discreet components that we could then re-use in other parts of the application.

I initially looked into the concept of partials in ASP.NET Core, and while these are great for reusing static markup, they’re not so great for building dynamic, data-driven content such as menus (which would be the first component I would in fact be developing).

Where your requirement is to reuse dynamic and / or data driven content, then the correct design approach is to use a ViewComponent. From the Microsoft documentation[^]

Quote:
New to ASP.NET Core MVC, view components are similar to partial views, but they’re much more powerful. View components don’t use model binding, and only depend on the data provided 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’s too complex for a partial view, such as:
- Dynamic navigation menus // bingo!! this is what we’re looking for!!

I won’t copy the entire list here, I’ve posted the link to the documentation so you can have a read of it for yourself.

So our menu tree structure is handled by a ViewComponent. All the business logic for building a user-specific menu is contained within the ViewComponent, and the ViewComponent returns the menu tree structure. This is then displayed by the Razor Pagethat is associated with the ViewComponent.

So building our application’s menu is encapsulated in a reusable, discreet and unit-testable ViewComponent. Going forwards, we will use ViewComponent’s for all of our UI components, and build up our Razor Pages from multiple ViewComponents.

This gives us huge benefits.

- Encapsulate the underlying business logic for a Razor Page in a separate component
- Allow for the business logic to be unit-tested
- Allow for the UI component to be reused across different forms
- Leads to cleaner code with separation of concerns

Here’s a (very) simplified example of how we’ve used a ViewComponent to build our menu tree structure. Note that all exception handling, logging etc has been removed for brevity.

Hide Copy Code

public class MenuItemsViewComponent: ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(int parentId, string email)
{
var response = await new MenuServices().GetModulesItemsForUser(parentId, email);

return View(response);
}
}

The ViewComponent calls one of our ASP.NET Web API services to retrieve the menu tree specified menu level and user. It then returns this wrapped inside an instance of IViewComponentResult, which is one of the supported result types returned from a ViewComponent.

Here is the (very) simplified Razor Page that displays the output from the ViewComponent. Note that all styling has been removed for brevity.

Hide Copy Code

@model Common.Models.MainMenuModels

@if (Model != null && Model.MenuItems != null && Model.MenuItems.Any())
{
foreach (var menuitem in Model.MenuItems)
{
<a asp-page=@menuitem.Routing>@menuitem.DisplayText</a>
}
}

And finally here’s how we invoke the ViewComponent from our layout page.

Hide Copy Code

@await Component.InvokeAsync("MenuItems", 0, "myemail@company.co.uk")

I am very impressed with the ViewComponent concept. From a design point-of-view, it is the correct approach if you are building forms that contain any sort of dynamic content. By allowing for clean separation of concerns and supporting unit testing, you can ensure your applications are far more robust and less likely to fail in production. These are just a couple of reasons why you should consider using ViewComponent’s in your own ASP.NET Core 2.0 applications. Why not give them a try.