Back to all posts

Using Blazor Sections For Complex Situations

Posted on Apr 06, 2026

Posted in category:
Development
ASP.NET

Not all applications are "template simple" to setup, and sometimes the seemingly "simple" things can become overwhelming to solve, and the final solution ends up being very simple.  Many of my Blazor projects to date have been line-of-business applications, and 99.9% of the content is behind a login, so extensive time and energy were not spent on SEO-related activities. Well, that's changing with a current solution that I'm working on, and we ran into a few issues, so I thought I'd share how we achieved our goal.

The Setup

The overall project consists of a single "App.razor" with InteractiveServer as the default rendering mode.  The application itself has two separate layouts, "AdminLayout.razor" and "MainLayout.razor", for different portions of the application.  The initial setup loads "common" JS in the app.razor file, with a <HeadOutlet/> for use by the individual layouts.

The layouts then did their thing with the <HeadContent> element for their custom CSS/JS, etc!

This all worked great!  BUT......

The Issue

As we continued building the publicly facing items, we found we needed to make changes, such as adding canonical URLs, meta descriptions, and other elements.

If we added another <HeadContent> due to the "Last In Wins" implementation, the entire functionality was destroyed, and our pages didn't work as expected!  

If you follow older documentation or blog posts, you'll find all kinds of solutions touted, including crazy things with JSInterop and lots of custom stuff.  It just didn't seem right to me that we would need to do that, and I was correct!

Introducing Blazor Sections

Blazor Sections were introduced in .NET 8 and give us the ability to control the content of a component from a child component, effectively supporting what we needed, a method to pass data up the chain to our Layout to add our SEO specific items when needed.  You define a section with a particular name and use a <SectionOutlet> component on the parent object, and use a <SectionContent> component on the child to set your desired content, using a SectionName or SectionId.

Now, this does still have a "Last in Wins" behavior within the Sections, but it allows us to accomplish what we are looking for.

<HeadOutlet> is controlled by the Layouts
<SectionContent> is controlled by the actual rendered pages!

This allows us to do things like the following within a Component for SEO purposes

Example Child Content Section
<SectionContent SectionName="page-head">
	<link rel="canonical" href="@NavigationManager.Uri" />
	@if(!string.IsNullOrEmpty(Article?.SeoDescription))
	{
		<meta name="description" content="@Article.SeoDescription" />
	}
</SectionContent>
    

And all we had to do was add <SectionOutlet SectionName="page-head" /> within the <HeadContent> of our Layout.

As you can see, a pretty quick fix for what was a bit of a troubling problem!  What other fun "It shouldn't have taken that long" type of issues have you come across?