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.

[Click on image for larger view.]

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.

[Click on image for larger view.]

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.

[Click on image for larger view.]

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.

[Click on image for larger view.]

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.

[Click on image for larger view.]

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


Keep Up-to-Date with Visual Studio Live!

Email address*Country*