It’s become very fashionable to build web applications as a series of smaller components, which can be composed together to form a fully-featured UI.

In fact this is probably the single biggest shift when moving from Razor Pages or MVC to Blazor, where instead of thinking about views or pages, you’re free to create as many components as you like, and use them wherever you like.

Components can really speed up your web development. Once you get used to the idea of breaking complex UI down into smaller pieces it quickly becomes second nature.

But what about MVC and Razor Pages? What if you’re using those frameworks and want a piece of the component action?

View Components?

Turns out there is a handy (but oft overlooked) feature in ASP.NET Core called View Components.

Here’s an example which uses one View Component to show “Hello World” to three different people.


<vc:greeting name="Boris"/>

@await Component.InvokeAsync("Greeting", new
    name = "Jon"

@await Component.InvokeAsync("Greeting", new
    name = "Steve"

We’ll come to why the first instance is different from the other two in a moment, but already we can see some advantages of this approach.

With our Greeting component we have a re-usable piece of UI which we can call with different parameters from anywhere in our Razor Pages application.

Here’s the Greeting View Component itself…


using Microsoft.AspNetCore.Mvc;

namespace RazorPageExamples.Pages.Components.Greeting
    public class GreetingViewComponent : ViewComponent
        public GreetingViewComponent()
        public IViewComponentResult Invoke(string name)
            return View("Default", name);

What’s in a name?

Note the name of this class ends with ViewComponent. That’s important for it to be recognised as a ViewComponent.

Alternatively you can call it whatever you like then use the ViewComponent attribute to achieve the same result.

 public class GreetingThing : ViewComponent {}

We’re free to use Dependency Injection in a ViewComponent (for example to inject a service, or something like MediatR to handle retrieving data).

The Invoke method will be, well… invoked, when the component is rendered.

We then return a view called Default, passing a string name as the model for that View.


@model string

    Hello @Model

Be careful where you put that view…

ASP.NET will look in several locations to find the view for your ViewComponent (by default).

/Pages/Components/<component-name>/Default.cshtml /Views/Shared/Components/<component-name>/Default.cshtml

You can specify any view name you like when you return the View and it will look in these folders for a View with that name.

I have a ViewComponent and I’m not afraid to use it!

Finally, to render this component we can use a couple of approaches.

The first is to use Component.InvokeAsync:

@await Component.InvokeAsync("Greeting", new
    name = "Steve"

Where we pass the arguments (name in this case) via an anonymous object as the second argument to InvokeAsync.

But you might prefer a more declarative approach which you can achieve using the vc tag helper…

<vc:greeting name="Boris"/>

Here we use the vc tag helper, specify the component name and parameters using kebab case.

Making the vc tag helper work

You might need to add this line to your _ViewImports.cshtml page to get that vc tag helper to work…

@addTagHelper *, RazorPageExamples

Where RazorPageExamples is the name of your project.

Components All The Way Down

As we move inexorably towards a web built on components, this feels like a handy way to step in that direction within your existing Razor Pages and MVC applications.

Here’s the source code for this example.

Just before you ride off into the sunset to replace all your pages with components, it’s worth noting you can render Blazor WASM Components in your existing applications, and in fact Blazor Server Components too.

Although broadly similar there are some key differences between using ViewComponents and Blazor Components in your applications so make sure to check out this excellent summary of the key differences by Andrew Lock.

Build better ASP.NET web applications, faster

I email every week with hints, tips and advice on how to push through all the noise to get your ASP.NET applications built.

Drop your email in the box below and I'll send new articles straight to your inbox.

I respect your email privacy. No spam, unsubscribe anytime with one click.