ASP.NET MVC Tip #35 – Use the NHaml View Engine
In this tip, I explain how you can use the NHaml view engine as the view engine for an ASP.NET MVC application. I demonstrate how to create NHaml views that display both static content and database records. I also discuss how you can use master pages and user controls with the NHaml view engine.
In this tip, I explain how you can use the NHaml view engine when building an ASP.NET MVC application. The NHaml view engine is an alternative view engine to the default Web Forms view engine. NHaml is a port of the popular RAILS Haml view engine for the .NET framework.
Why use NHaml? NHaml enables you to overcome the verbosity of XHTML. What JSON is to XML, NHaml is to XHTML.
XHTML is an extremely verbose language. You need to do a lot of typing to do anything. For example, if you want to display some text in bold and italics, you have to type the following:
<strong><em>You should never yell!</em></strong>
The NHaml syntax for building a view is extremely terse. If you want to display some text in bold and italics, you can just type the following:
%strong %em You should never yell!
Notice that you don’t need to create a closing <strong> or <em> tag. The NHaml template processor creates these tags for you automatically.
Spaces are extremely important when using NHaml. You use spaces to indicate which element is contained in another element. The <em> tag gets rendered in the <strong> tag because the <em> tag is indented by two spaces beneath the <strong> tag.
Another advantage of this terse syntax is that it makes it easier to mix script with your XHTML markup. Using the Web Forms view engine, here’s how you would display a set of database records stored in view data:
<ul> <% foreach (var m in ViewData.Model) { %> <li> <%= m.Title %> </li> <% } %> </ul>
Here’s how you would format the same set of database records with the NHaml view engine:
%ul - foreach (var m in ViewData.Model) %li =m.Title
Depending on the configuration of your brain (your innate sensitivity to spaces), you will either find the NHaml view engine appealing or not. You will either find an NHaml view unreadable or you will be enamored by its terse simplicity. If you are a member of the latter camp, read on.
Installing and Configuring NHaml
The primary developer behind NHaml is Andrew Peters. You can read his blog entries on NHaml at:
He is releasing NHaml under the MIT open source license (one of the most permissive of the open source licenses). Anyone can download the source code and use NHaml in both commercial and non-commercial applications.
In order to use NHaml, you must complete the following steps:
Step 1 – Download the Source Code
You can download the entire source code for NHaml from the Google Code website at:
Google Code uses Subversion for its source control system. To download the NHaml code, you’ll need to use a Subversion client. I recommend that you download the TortoiseSVN client from:
After you install the TortoiseSVN client, you can download the source code for NHaml by creating a new folder on your computer (anywhere), right-clicking the new folder, and selecting the menu option SVN Checkout (see Figure 1). Enter the following URL for the URL of the repository:
http://nhaml.googlecode.com/svn/trunk/
After you click the OK button, all of the files from the Google Code repository for NHaml will be downloaded to your computer.
Figure 1 – Checkout of NHaml from Google Code
Step 2 – Add References to the NHaml Assemblies
Before you can use NHaml with a new ASP.NET MVC project, you must add the necessary assembly references to the project. After creating a new ASP.NET MVC project, select the menu option Project, Add Reference. Under the Browse tab, navigate to the folder that contains the NHaml source code (the folder you created in the previous step).
You need to add references to the following two assemblies:
NHaml.dll
NHaml.Web.Mvc.dll
Step 3 – Use the NHaml Controller Factory
The default view engine for ASP.NET MVC is the Web Forms view engine. In order to switch to the NHaml view engine, you need to enable the NHaml Controller Factory in your application’s Global.asax file. Modify your Global.asax file so that it looks like Listing 1.
Listing 1 – Global.asax.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using NHaml.Web.Mvc; namespace Tip35 { public class GlobalApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } ); } protected void Application_Start() { ControllerBuilder.Current.SetControllerFactory(new NHamlControllerFactory()); RegisterRoutes(RouteTable.Routes); } } }
Only one line of code has been added to the Global.asax.cs file in Listing 1. The NHaml controller factory is registered as the default controller factory with the following line of code:
ControllerBuilder.Current.SetControllerFactory(new NHamlControllerFactory());
Step 4 – Modify the Web Configuration File
There is one final step that you must complete before using NHaml. You must add a new NHaml section in your web configuration file.
The NHaml section is used to set whether or not NHaml is in production mode or development mode. In production mode, views are not recompiled automatically when the source of a view is changed. Therefore, while developing an application that uses NHaml, you’ll want to put your application in development mode. When you are ready to go live, you’ll want to place your application in production mode.
Add the following element within your root web configuration (web.config) file configuration\configSections element:
<section name="nhaml" type="NHaml.Configuration.NHamlSection, NHaml" />
Next, add the following element right below the closing tag of the configSections element:
<nhaml production="false" compilerVersion="3.5" />
This configuration element places your NHaml application in development mode.
Creating an NHaml View
You create an NHaml view by creating a file that ends with the extension .haml. Because Visual Studio does not have an NHaml view template, you must create NHaml views by creating some other file type (such as an HTML file) and changing the file extension to .haml.
A sample NHaml view is contained in Listing 2.
Listing 2 – \Views\Home\Index.haml
!!! %html{xmlns="http://www.w3.org/1999/xhtml"} %head %title My Index View %body %h1 =ViewData["message"]
The NHaml Index view in Listing 2 is a really simple view. It contains mostly static XHTML content. The only dynamic content is the view data displayed in the body of the view (see Figure 2). The value of the message key from view data is displayed.
Figure 2 – The NHaml Index View
The view in Listing 2 renders the XHTML document in Listing 3. This is a valid XHTML document. Comparing the sizes of the files in Listing 2 and Listing 3 illustrates the motivation behind using the NHaml view engine.
Listing 3 – Index.haml Rendered Output
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>My Index View</title> </head> <body> <h1> Welcome to ASP.NET MVC! </h1> </body> </html>
Realize that spaces are extremely important within a NHAML view. You use exactly two spaces to indicate a nesting relationship with the element in the preceding line. When building NHaml views, I recommend that you select the Visual Studio menu option Edit, Advanced, View White Space. Selecting this menu option will make it easier to see the spaces in your views (see Figure 3).
Figure 3 – Show White Space Enabled
Displaying Database Data
You can use view data within an NHaml view to represent database data. For example, the view in Listing 4 displays all of the records from the Movies database table by retrieving the records from view data (see Figure 4).
Figure 4 – Displaying database data with NHaml
Listing 4 – Movies.haml
!!! %html{xmlns="http://www.w3.org/1999/xhtml"} %head %title My Index View %body %h1 Movie List %ul - foreach (var m in ViewData.Model) %li =m.Title
Notice that the foreach statement is preceded by a dash -. You use a dash to indicate that the code on the line should be evaluated as a statement instead of an expression. You use the equal sign = to indicate that the following code should be output to the browser.
There is no concept of a typed NHaml view. The NHaml engine does some internal magic to cast the Model object to the right type.
Using Master Pages and Partials
The NHaml view engine works with master pages (layouts) and user controls (partials). You can use a master page to create a common layout for the NHaml views in your application and you can use user controls to reuse visual content across multiple views.
The use of master pages in NHaml is driven by convention. You create a file named Application.haml in your Shared folder. This file becomes the master page for your application automatically.
For example, the file in Listing 5 acts as a master page.
Listing 5 – \Views\Shared\Application.haml
!!! %html{xmlns="http://www.w3.org/1999/xhtml"} %head %title My Application %body %h1 Master Page _
Notice that the final line in Listing 5 consists of a single underscore _. This underscore marks the region that can be overridden in a particular view (the underscore acts like a ContentPlaceHolder control).
The NHaml view in Listing 6 uses the master page.
Listing 6 -- \Views\Home\ShowMaster.haml
%ul - foreach (var movie in ViewData.Model) _ Movie
The content rendered by the view in Listing 6 is plugged into the area of the master page marked by the underscore. The view loops through the movie records represented by the ViewData.Model property.
Notice the syntax _ Movie. You use this syntax to add a user control (partial) to a view. The syntax _ Movie adds a user control named _Movie.haml to the view. The _Movie.haml user control is contained in Listing 7.
Listing 7 -- \Views\Home\_Movie.haml
%div Title: =movie.Title %br / Director: =movie.Director %hr /
There are two special things that you should notice about the user control in Listing 7. First, notice that the name of the user control starts with an underscore _. That is a requirement.
Second, notice that the user control can use a variable from its parent view. The user control is using the movie variable that represents a particular Movie database record. The user control gets the movie variable from the view in Listing 6.
When you request the ShowMaster view, the page in Figure 5 is rendered. The content of the master page, the view, and the user controls are merged and rendered as a single page.
Figure 5 – ShowMaster view
Note: I could not figure out a way to selectively apply the Application.haml master page to only certain views. Therefore, I renamed the Application.haml file to xApplication.haml in the code download at the end of this tip so that the other views described in previous listings would not use the master page.
Summary
One of the greatest strengths of the ASP.NET MVC framework is its extensibility. There is almost always a way to modify any feature of the framework. The most dramatic way in which you can change the behavior of the ASP.NET MVC framework is to change its view engine.
In this tip, I demonstrated how to swap out the default Web Forms view engine for the NHaml view engine. I showed how you can use view data, master pages, and user controls with the NHaml view engine. And, I hope, I have given you a sense of the unlimited possibilities inherit in the ASP.NET MVC framework.
Download the Code