Issues

ViewComponents in Umbraco 9

Umbraco 9 running on .NET 5 is just around the corner and with that comes a new concept called ViewComponents that you’ll need to be familiar with from this point forward.

What are ViewComponents? How and when do we use it? These are some of the question I will cover in this article so that you are up to speed when you jump on your first Umbraco 9 project.

What are ViewComponents?

"View components are similar to partial views, but they're much more powerful.”

- Microsoft: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-5.0

View components are supposed to replace the traditional Controller (SurfaceController) / Partial View relationship and instead offer a more modular approach of separating your views in to several smaller units.

Each ViewComponent is responsible for its own business logic and rendering which is good for testability and the Separation-of-concerns principle. They are perfect for rendering page content that are reused multiple times in your application and need to run independently. Examples could be a header, navigation, footer but also Nested Content or BlockList items. Think of these sections of your site as standalone modules that can be invoked and run from anywhere in your application regardless of context.

"Modular programming is separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.”

- Wikipedia: https://en.wikipedia.org/wiki/Modular_programming

We can still use all the fancy tech we are used to, like Dependency Injection, in our ViewComponents and inject whatever dependencies we need to render that piece of content.

At the end of the day you’ll notice that ViewComponents make a lot much more sense than the old Controller / Partial View approach and I promise you’ll come to love ViewComponent.

Enough fancy words, show me the code!

How to create and invoke a ViewComponent:

In this example lets create a ViewComponent for our Footer and render it on the bottom of every page. So first we need to create a class called FooterViewComponent:

public class FooterViewComponent : ViewComponent
{
	public IViewComponentResult Invoke()
	{
		return View(new FooterViewModel()
		{
			Text = “Footer text goes here…”
		});
	}
}

It doesn’t matter where you create this class, it’ll be picked up regardless of where you create it. In other words: it’ll be picked up automatically so you don’t need to worry about registering it somewhere in a Startup class or create some sort of IUserComposer for you ViewComponent.

All you need is this ViewComponent class and it’ll work right of the bat. Nice huh?

Following the modular approach I like to organise it so that all the classes that I need for my ViewComponent are in the same folder. This way I know where all the classes for this components live and it will make it a whole lot easier for me when I’m reusing ViewComponents between different projects (Copy/Paste):

The next thing we need to do is create the view for this ViewComponent.

By default, this view needs to be: /Views/Components/{NameOfYourComponent}/Default.cshtml.

You can specify your own view path if you wish, but for the sake of keeping this a basic example, we’ll create /Views/Components/Footer/Default.cshtml:

@model FooterViewModel
@if (!string.IsNullOrEmpty(Model?.Text))
{
    <footer class="section--themed">
        <div class="container">
            <div class="row">
                <div class="col-md-12 ta-center">
                    @Model.Text
                </div>
            </div>
        </div>
    </footer>
}

And the last thing we need is to invoke this ViewComponent where we need it to be rendered.

You can invoke a ViewComponent from basically anywhere (even from within a Controller or another ViewComponent) but since this is our Footer, we want it rendered at the bottom of every page, so we’ll invoke it from our Master.cshtml file using:

@(await Component.InvokeAsync("Footer"))

There are other ways of rendering your view component such as tag helpers which you can read more about on the official Mictosoft documentation on ViewComponents: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-5.0

Tada!

Now we have a Footer rendered at the bottom of every page!

And if we need to tweak this footer in the future all the logic needed to run this footer is handled from within the newly created ViewComponent class, so it’ll make refactoring and extending our footer much easier.

Should I use a ViewComponent or should I use the good old Partial View?

Are we supposed to only use ViewComponents from now on and say goodbye to the traditional partial view?

No, there are still cases where a simple partial view is enough and makes more sense than a ViewComponent and I thought I would break down when I think you should use one or the other:

Does your view only contain static html?

Stick with a simple partial view.

Are you splitting up a big view in to several smaller views but still using the same shared initial logic and view model?

Again, use a partial view. If all these views share the same model and initial logic there is no need to add the extra layer of complexity with a ViewComponent.

Does your view need to handle separate business logic and/or dedicated view model?

Use a ViewComponent. This is where ViewComponents are powerful because you can create a standalone unit that handles its own logic and rendering that you can reuse over and over in your application.

Conclusion

As you probably noticed, we have just scratched the surface when it comes to ViewComponents. This was just a basic example to get you started without adding too much complexity or configuration. The Microsoft documentation on ViewComponents is great and you’ll find a bunch of ways you can improve and configure you ViewComponents and make them work in a way that works for you, but in a nutshell this is the simples most straight-forward way of creating a ViewComponent in .NET 5.

I hope you enjoyed it!

Cheers friends! ❤️

Dennis Adolfi

Dennis Adolfi is a developer at Knowit, living in Gothenburg, Sweden. He’s been an active member of the Umbraco community for many years writing blog posts & tutorials, hosting events, teaching and helping out in the Umbraco forum, for which he was rewarded MVP in 2016. He’s also an Umbraco Master and he loves Test Driven Development. When he’s not producing code he enjoys making his body super tired by repeatedly lifting heavy things up in the air and then putting them back down again.

comments powered by Disqus