ASP MVC Razor: Using Sections

April 26, 2016

In order to get a consistent looking website, many designers use a common layout or master page. We used to achieve this by creating a page and including a header file and a footer file.  The problem with that approach is that we have a header file with a lot of start tags (like <body>) but no end tags and a separate footer file with a lot of end tags (like </body>) and no start tags; it’s easy to mess up and difficult to view.

Using a layout file we can actually see the complete page, with all the tags correctly matching. Then we inject our page body in the correct place by using a placeholder @RenderBody.

Using Razor syntax, the layout will look like this:

 <!DOCTYPE html>
 <html>
   <head>
     <title>Test Page</title>
     <link href="css/bootstrap.min.css" rel="stylesheet">
     <script src="js/jquery.js"></script>
   </head>
  <body>
    @RenderBody()
  </body>
 </html>

So our .cshtml page (I’ll refer to it as the body page) can be made from pure HTML, as easy as:

 <div class="mybodyclass">
   This is our contents page
 </div>

The actual web page will be rendered as:

 <!DOCTYPE html>
 <html>
   <head>
     <title>Test Page</title>
     <link href="css/bootstrap.min.css" rel="stylesheet">
     <script src="js/jquery.js"></script>
   </head>
   <body>
     <div class="mybodyclass">
       This is our contents page
     </div>
   </body>
 </html>

That’s good, but in practice we often need to add some other items to the layout too.
Say, for example, we have a different style sheet for many of our body pages. We may also
have some javascript files which we would like to include just before the closing </body> tag. We can achieve that using Sections.

Sections are in two stages. First, we decide where the section will be in the layout page and then add the directive @RenderSection(“head”, required: false).

The first parameter (“head”) is the name of the section and you can call it whatever makes sense. I’ll call this one “head” because I intend to use it in the head section, but I could have called it “headerfiles” or whatever.

The second parameter (“required:false”) is stating if the section must be defined in the body page. If you use “required:true” then each body page must define that section. I’m using false because not all the body pages will have their own css files.

RenderSection is overloaded and required defaults to true, so you can write @RenderSection(“somename”, required: true) as @RenderSection(“somename”)

You can, and often do, have more than one section. I’ll add a second section at the bottom of the page so that we can add javascript files at the bottom of the page. I’ll define this as
@RenderSection(“Scripts”, required: false).

So our updated layout file is:

 <!DOCTYPE html>
 <html>
   <head>
     <title>Test Page</title>
     <link href="css/bootstrap.min.css" rel="stylesheet">
     @RenderSection("head", required: false)
     <script src="js/jquery.js"></script>
   </head>
   <body>
     @RenderBody()
     @RenderSection("Scripts", required: false)
   </body>
 </html>

To write into these sections all we need to do is use @section name{ } in our body files, like this:

 @section head{
   <link href="css/mycustom.css" rel="stylesheet" />
 }
 <div class="mybodyclass">
   This is our contents page
 </div>
 @section Scripts{
   <script src="js/mycode.js"></script>
 }

Note we don’t have the name in quotes, it just needs to match a RenderSection name.

Finally, our web page will render as:

 <!DOCTYPE html>
 <html>
   <head>
     <title>Test Page</title>
     <link href="css/bootstrap.min.css" rel="stylesheet">
     <link href="css/mycustom.css" rel="stylesheet" />
     <script src="js/jquery.js"></script>
   </head>
   <body>
     <div class="mybodyclass">
       This is our contents page
     </div>
     <script src="js/mycode.js"></script>
   </body>
 </html>