Understanding Layouts in ASP.NET Core: Using Sections to Build Flexible Content
I recently decided that my website needed some love and maintenance. I'd been hosting it using WordPress for a zillion years and I'd started getting fed up with how much it was costing me to run it. So I did what every busy developer does -- I decided to write my own content management system / blog engine using Cosmos DB and ASP.NET Core MVC. It came out pretty darned good and my ASP.NET MVC skills got a workout and a refresher.
One big thing I learned when I was writing all the search engine optimization (SEO) code was about sections and the @RenderSection helper method.
Why Would I Care about @RenderSection?
In order to get your site to be SEO compliant and to help your site and content to show up in search engines, there are a whole bunch of values that you'll want to put into the HTML of your webpages. Lots of these values are part of the Open Graph Protocol and are the machine-readable metadata that a search engine will use to "understand" your content. These values should be part of the <head> tag of your HTML page and show up as <meta> tags.
Some of the values that I'm using on my website are:
- og:site_name -- name of the website
- og:title -- the title of the page or blog post
- og:description -- description of the website or an excerpt of a blog post
- og:type -- type of content (website, article, other)
- og:image -- image for the page or blog post
The image below is a screenshot of the meta tags that I'm setting on my home page. As you can see, there's kind of a lot of them and they all show up in the <head> tag.
If this were a static site, I'd just put the values that I need in the various hard-coded html files for my site. But this is a dynamic page and the meta values are going to change a lot from page to page and blog post to blog post.
The part that was tripping me up was that the values needed to be in the <head> tag.
A Little Bit About the Structure of an ASP.NET Core MVC Application
In order to point out why getting values into the <head> tag was a problem, let me just pause for a moment to review the structure of an ASP.NET Core MVC View. The views are all the *.cshtml
files that live in your web project. These cshtml
files use a templating syntax called Razor that allows you to mingle C# code and HTML markup that gets turned in to rendered HTML that shows up in your browser.
So far so good.
The cshtml/razor/MVC syntax creates a hierarchy of these views that all work together to allow you to reuse logic and HTML so that you avoid tons of duplicated code. Here's an example. Let's say that I want to display a blog post. The display logic for a blog post lives in Entry.cshtml
and when it gets run, the MVC app knows that Entry
is only part of the display logic and that it also has to render _Layout.cshtml
, too.
The _Layout.cshtml
file contains all the basic structure of a web page like the tags, the <html> tags, the <body>, and also the <head> tag and its contents. It also has a call to @RenderBody
and this is where the contents of Entry.cshtml
gets dropped in in order to make a fully rendered webpage.
My Problem: How Do I Get Dynamic Content from a View into _Layout.cshtml?
Back to my problem. I need to be able to generate those "og:" <meta> values and make them show up in the <head> tag. The Entry.cshtml
view will have access to the information that should be in the those values but the problem is that the actual tag lives in a totally different file. So how to get those <meta> values but the problem is that the actual <head> tag lives in a totally different file. So how to get those <meta> tag values from Entry.cshtml
to the <head> tag in _Layout.cshtml
?
The Answer: Sections and @RenderSection
Razor and cshtml to the rescue! It turns out that you can define something called a section that allows you to pass content from the child view to the layout view. All you need to do is to put a @RenderSection
directive wherever you want that content to show up. In this case (see below), I put a @RenderSection
called HeadContent
inside of the <head> tag of _Layout.cshtml
. This basically just says to the templating engine, "if you've got content for this section, drop it here." I'm also marking it as required = false
meaning that if there's no content supplied, to just leave this section as blank.
Over in my Entry.cshtml
view, you can use the @section
directive to set all the values that should show up in the section. So as you can see below, Entry.cshtml
has access to a BlogEntry
class that contains all the data for a blog post via the @model
directive. Once I've got that data, it no big deal to just drop in the values.
Then at runtime, all the generated <meta> data from the entry, shows up in the <head> tag. All I needed to do was make sure that the name I supplied on my @section
matches the name supplied in the @RenderSection
.
- @section HeadContent
- @RenderSection("HeadContent", required: false)
Summary
In this post, we explored how to leverage @RenderSection
in ASP.NET Core MVC to solve layout-related challenges and create dynamic, flexible web pages. Whether you're building a custom blog engine or enhancing your web application's structure, sections provide a clean, modular approach to content management. By integrating sections effectively, you can simplify your layout design and unlock more maintainable solutions for rendering dynamic content.
About the Author
Benjamin Day is a consultant, trainer and author specializing in software development, project management and leadership.
Posted by Benjamin Day on 12/17/2024