Learning Razor-Shared Content & Layout

by rhernandez 13. November 2010 06:54

As web developer’s in the .NET world we have been spoiled by the advantages of using centralized master pages for managing shared content and layout since the 2.0 version of the .NET Framework.  The ASP.NET MVC 1.0 Framework was no exception we were able to take advantage of our knowledge of ASP.NET master page’s to layout the content of our views.  Now, Razor is no exception either, we still will have the ability to centralize the way content is laid out in our application but some of the mechanics of how the process works have changed.  In fact, one could argue that the way layout is defined in Razor is more inline with the way the Spark view engine (http://www.sparkviewengine.com) does rendering than traditional master pages.

 

Layout Pages

In Razor the concept of a master page is equivalent to a layout page, and one could argue that a similar comparison could be made between the concept of ASP.NET placeholders and sections in Razor.  The following snippet shows what a very basic Razor layout page looks like.  As you can see this is mostly a plain vanilla HTML file the only exception is the directive @RenderBody() which is just a method call that tells Razor where to render the Contents of the child view.

 

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>My WebSite</title>
    </head>
    <body>
        @RenderBody()
    </body>
</html>

 

A basic child view would just specify its layout page and provide the content that is going to be rendered by the @RenderBody() method. As you can see in the following snippet the code for the template is very minimalistic and elegant.

 

@{
    Layout = "~/_SiteLayout.cshtml";
}

<h1>Hello World!</h1>
<h2>Hello World!</h2>
<h3>Hello World!</h3>

 

So far the two samples (snippets) have been very basic, so lets complicate things a bit what if we wanted to have a three column layout.  Well we would still want the main section of the page to drive of the @RenderContent() functionality but for the additional sections you can use Razor’s @RenderSection() method to define additional section’s that can be filled with content from our child views.  The following is the snippet for a three column layout page using CSS.

 

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>My WebSite</title>
        <style>
            #container { width: 700px; }
            #left { float: left; width: 150px; }
            #content { padding: 0 210px 0 160px; }
            #right { float: right; width: 200px; }
            .clear { clear: both; }
        </style>
    </head>
    <body>
        <div id="container">
            <div id="left">
                @RenderSection("left", required:false)
            </div>
            <div id="content">
                @RenderBody()
            </div>
            <div id="right">
                @RenderSection("right", required:false)
            </div>
            <div class="clear"></div>
        </div>
    </body>
</html>

 

The “required:false” parameter specifies if the child view is required to provide content for this section in our case the left and right sections will be optional.   The following is a sample snippet of a page that provides content for all sections, as you can see it is still very minimalistic and elegant.

 

@{
    Layout = "~/_3ColLayout.cshtml";
}

<h1>Main Content</h1>

@section left {
    <h1>Left Content</h1>
}

@section right {
    <h1>Right Content</h1>
}

 

Well, this sums up all the basic information you should need to get started with using layout pages in Razor.  Thanks for reading!

Learning Razor–Writing an Inline Recursive HTML Helper

by rhernandez 10. November 2010 08:54

I have been using Spark (http://www.sparkviewengine.com) as my default view engine for the past 5 or 6 months and I love everything about it.  I like its elegance, simplicity and I depend on some of its features to be efficient in doing most of my daily tasks.   That being said, there is a new kid on the block and his name is Razor.  Razor, will be an out of the box alternative for the ASP.NET WebForm’s view engine for ASP.NET MVC3 (Read Scott Guthrie’s blog on the topic here).   I don’t intend to write a full blown tutorial on Razor,  but as I learn the basics for this alternative view engine, I will try to write some “Learning Razor” posts that relate my experience in learning this new technology.

 

Writing an Inline Recursive Html Helper

The Spark view engine provides you with the ability to define inline macros that allow for recursive calls (Read Louis DeJardin blog on the topic here, and additional documentation here).  These macros are extremely useful for rendering a hierarchical structure such as the one in the following snippet.

 

<ul>
  <li>Fuller, Andrew
    <ul>
      <li>Davolio, Nancy</li>
      <li>Leverling, Janet</li>
      <li>Peacock, Margaret</li>
      <li>Buchanan, Steven
        <ul>
          <li>Suyama, Michael</li>
          <li>King, Robert</li>
          <li>Dodsworth, Anne</li>
        </ul>
      </li>
      <li>Callahan, Laura</li>
    </ul>
  </li>
</ul>

 

Now, the Razor view engine allows you to easily build a hierarchical structure by the use of inline HTML helpers that can be called recursively.  The following is a basic snippet of a “Hello World” inline HTML helper, and a call to trigger its functionality.

 

@HelloWorld("Roberto!")

@helper HelloWorld(string name) {
    <h1>Hello World! @name</h1>
}

 

Finally, if we wanted to output the html from the first snippet using Razor we could write the following inline HTML helper.

 

@model IEnumerable<OrganizationNodeViewModel>
@using MVC3.Playground.ViewModels;
@{
    View.Title = "OrganizationTree";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>OrganizationTree</h2>

@OrgTree(Model, null);

@helper OrgTree(IEnumerable<OrganizationNodeViewModel> nodes, int? parentId) {
    if (nodes.Any(n => n.ParentId == parentId)) { 
    <ul>
        @foreach (var node in nodes.Where(n => n.ParentId == parentId)) {
            <li>
                @node.DisplayName
                @OrgTree(nodes, node.Id)
            </li>
        }
    </ul>
    }
}

The Author



Roberto Hernández

 

Currently an Developer Extraordinaire at InfernoRed Technology based out of Northern Virginia. I have been architecting and building software solutions using Microsoft technology for the past 14 years. I was awarded as a Microsoft MVP in C# in 2007,2008 and 2010. I am originally from the Dominican Republic, and the proud father of two beautiful daughters that make my life special. You can track me down on twitter (@hernandezrobert) and on this blog at http://www.overridethis.com.


 

Stack Overflow profile for Roberto Hernandez at Stack Overflow, Q&A for professional and enthusiast programmers

INETA Community Speakers Program

 

 

Recent Posts