Using Sections and Partials to Manage Razor Views

How many of you out there are using .NET MVC to produce web applications today? Quite a lot of hands there I see, and just as I suspected.

This probably means that a lot of you will be using the built in Razor View engine, and will most likely be creating your views in a shared '_Layout.cshtml' file in your shared views folder.

Probably that looks something like this:

<!DOCTYPE html>
<html>
  
  <head>
    <title>@ViewBag.Title</title>
  </head>
  
  <body>
    
    @RenderBody()  
 
  </body>
</html>
 

As you likely know, it's the render body call that injects your actual individual page content into the template file, and in most cases the majority of people only ever use this, and put the main meat of what they need in the individual views themselves.

Did you know however, that it's amazingly easy to reuse parts of code and for that matter other shared views inside your Razor templates? Let's look at this using the following example.

Most websites have a handful of different template pages. From experience, in most of what I do, there are generally three distinct things that I need to have; these are:

1. A page template that stretches the full width of the display, and has a side bar and main content area.

2. A page template that stretches the full width of the display, but has no side bar with content that's generally left aligned.

3. A page template that forms a singular central column irrespective of the display size, and where left and right margins are auto to keep the content centered.

In each case, that's three Razor master layouts to maintain, each with its own set of headers, footers, script tags as well as other common furniture such as nav bars, logos, etc.

Now I'm guessing that everyone reading this knows the pain of updating the same thing in several files, and working with multiple templates in this fashion generally means that if you decide to start using 'somenewjs.js' then that's three changes you need to make in three files.

Take that one step further and imagine that's 20 different template files.  Not a fun prospect right?

HTML partials and sections can (and do) greatly help ease this burden.

Taking our example above, lets expand that to three different templates:

<!DOCTYPE html>
<html>
  
  <head>
    <title>Template 1</title>
    <script src="jquery.js"></script>
  </head>
  
  <body>
    <h2>Template 1</h2>
    @RenderBody()  
 
  </body>
</html>
----------------------------------
<!DOCTYPE html>
<html>
  
  <head>
    <title>Template 2</title>
    <script src="jquery.js"></script>
  </head>
  
  <body>
    <h2>Template 2</h2>
    @RenderBody()  
 
  </body>
</html>
-----------------------------------
<!DOCTYPE html>
<html>
  
  <head>
    <title>Template 3</title>
    <script src="jquery.js"></script>
  </head>
  
  <body>
    <h2>Template 3</h2>
    @RenderBody()  
 
  </body>
</html>

You can see immediately, that to change 'JQuery' you need to make three changes.  However, a simple change and a new file, removes that requirement immediately.

Remove the script tag from each of the templates, and replace them with a call to 'Html Partial' as follows:

<!DOCTYPE html>
<html>
  
  <head>
    <title>Template 1</title>
    @Html.Partial("_HeaderScripts")
  </head>
  
  <body>
    <h2>Template 1</h2>
    @RenderBody()  
 
  </body>
</html>

Do the same for all three templates.

Then in your views/shared folder, create a new view file called '_HeaderScripts.cshtml' and into it add the original script tag you previously had in your templates:

<script src="jquery.js"></script>

If you now decide to add JQuery UI, all you need to do is add it the header scripts file and immediately all your Razor templates will start using it:

<script src="jquery.js"></script>

<script src="jqueryUI.js"></script>

Using Html partials has two small drawbacks though.

1. The file must exist, it's not optional

2. You can't pick and choose different content for different views

This is where Razor sections come into play.  A section is something you define in your Razor views that you can flag as being optional or required, and which you then provide the implementation in your separate views when creating.

Now you might be thinking to yourself, well this is just like putting all my content into a single view file as I did before, and largely you would be right about that, except using sections means you can force your content to appear at a specific given place in your Razor template.

For example, it's now common best practice to put most if not all of your JavaScript includes at the bottom of your HTML page, just inside the body tag.

By using an appropriately positioned Razor section, you can ensure that this always happens, as the following shows:

<!DOCTYPE html>
<html>
  
  <head>
    <title>Template 1</title>
    @Html.Partial("_HeaderScripts")
  </head>
  
  <body>
    
    <div class="span9">
      @RenderBody()  
    </div>
 
    @RenderSection("FooterScripts", false)
 
  </body>
</html>

In your actual view, you then just simply need to define the following:

<p>This is some page content right here.</p>
@section FooterScripts
{
  <script type="javascript">
    // JS code goes here  
  </script>
}
 

As you can see above, the render section call has 'false' in it; this marks our section as optional, which means if it's not defined in your view, the compiler won't abort compilation because it's missing.

If you set the second parameter to true, then compilation won't succeed unless a view has a given section defined.

Putting all of what we've discussed so far together, and thinking about a structure can then give you amazing flexibility in your template pages and make maintaining them easier.

We'll close this post by presenting a layout structure that I very often use in .NET.

<!DOCTYPE html>
<html>
  
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE" />
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    @Html.Partial("_globalHeaders")
    @RenderSection("UserCss", false)
  </head>
  
  <body>
    
    @Html.Partial("_NavBar")
    <br />
    
    <div class="page">
      
      <div class="container">
        <div class="row">
        
          <div class="span3">
            <div class="well well-shadow">
              @Html.Partial("_SideMenu")
            </div>
 
            @RenderSection("ExtraSidebar", false)
          </div>
 
          <div class="span9">
            @RenderBody()  
          </div>
 
        </div>
      </div>
 
    </div>
 
    <footer class="container-fluid footerText">
      <p>My Footer goes here</p>
    </footer>
 
    @Html.Partial("_globalFooters")
    @RenderSection("UserScripts", false)
    @RenderSection("Templates", false)
    @RenderSection("Dialogs", false)
 
  </body>
</html>
 

As you can see, this layout is actually designed to accommodate a Twitter Bootstrap page that has dialogs, templates and other furniture on a page by page basis, but also allows for both a global sidebar and extensions to that side bar in individual views.

If there's anything you'd like to see covered in this column please feel free to reach out to me on twitter @shawty_ds or come and look me up on Linked-In where I help run the 'Linked.Net (Lidnug)' user group.



Related Articles

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The explosion in mobile devices and applications has generated a great deal of interest in APIs. Today's businesses are under increased pressure to make it easy to build apps, supply tools to help developers work more quickly, and deploy operational analytics so they can track users, developers, application performance, and more. Apigee Edge provides comprehensive API delivery tools and both operational and business-level analytics in an integrated platform. It is available as on-premise software or through …

  • IT departments are embracing cloud backup, but there's a lot you need to know before choosing a service provider. For example, did you know: That encryption doesn't guarantee privacy? That you could lose data by choosing the wrong cloud? That cloud backup doesn't have to be slow? Learn all the critical things you need to know by accessing the white paper, 5 Things You Didn't Know About Cloud Backup.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds