The Big View Engine Comparison – Razor vs. Spark vs. NHaml vs. Web Forms View Engine
One of the cool things about ASP.NET MVC (and other MVC web frameworks) is its capability to change the default view engine with a Microsoft or a 3rd-party one. ASP.NET MVC currently has a few options for view engine alternatives:
- The web forms view engine – this view engine, with the ASP-like syntax, is the default one for ASP.NET MVC 1 and 2 applications.
- Razor – the new view engine which will be the default one for ASP.NET MVC 3 applications.
- Spark – an open-source view engine which aims to seamlessly integrate code and HTML.
- NHaml – a port of the Ruby on Rails successful view engine named Haml. This open-source view engine aims to replace HTML tags with an easier to read and better organized syntax.
Note: Spark and NHaml are currently available for ASP.NET MVC 2. NHaml also doesn’t support .NET 4 at the moment. I believe that they will become available for version 3 as soon as it is out (moreover, they are open-source so you can help getting there!). Razor, on the other end, is not available on ASP.NET MVC 2 and below.
In this post I’ll go through the basic operations we do with our views and show you how to get them done with the different view engines mentioned above.
Displaying Variable Content
Here I’m comparing the way to present the content of ViewData["Message"] as an html-encoded string.
The Web Forms View Engine
<%: ViewData["Message"] %>
Razor
Spark
${Html.Encode(ViewData["Message"])}
NHaml
Conditions
Here I’m comparing the way of writing an if condition to display “<p>Party</p>” between 6AM and 9PM and “<p>It’s bed time</p>” between 9PM and 6AM.
The Web Forms View Engine
<% if (DateTime.Now.Hour > 20 || DateTime.Now.Hour < 6)
{ %>
<p>It's bed time!</p>
<% } else { %>
<p>Party!</p>
<% } %>
Razor
@if (DateTime.Now.Hour > 20 || DateTime.Now.Hour < 6) {
<p>It's bed time!</p>
} else {
<p>Party!</p>
}
Spark
<if condition='DateTime.Now.Hour > 20 || DateTime.Now.Hour < 6'>
<p>It's bed time!</p>
</if>
<else>
<p>Party!</p>
</else>
Another way of doing that in Spark (writing the condition inside the <p> tag):
<p if='DateTime.Now.Hour > 20 || DateTime.Now.Hour < 6'>
It's bed time!
</p>
<else>
<p>Party!</p>
</else>
NHaml
- if (DateTime.Now.Hour > 20 || DateTime.Now.Hour < 6)
%p= "It's bed time!"
- else
%p= "Party!"
Loops
Here I’m comparing the way to declare a list in the view and create an <ul>-<li> HTML list out of it.
The Web Forms View Engine
<% var list = new List<string>() { "WebForms", "Razor", "Spark", "NHaml" }; %>
<ul>
<% foreach (var item in list) { %>
<li><%: item %></li>
<% } %>
</ul>
Razor
@{ var list = new List<string>() { "WebForms", "Razor", "Spark", "NHaml" }; }
<ul>
@foreach (var item in list) {
<li>@item</li>
}
</ul>
Spark
<var list='new List<String>() { "WebForms", "Razor", "Spark", "NHaml" }'/>
<ul>
<li each='var item in list'>
${item}
</li>
</ul>
NHaml
- var list = new List<String>() { "WebForms", "Razor", "Spark", "NHaml" }
%ul
- foreach (var item in list)
%li= item
Displaying a Form
Here I’m comparing the way to write a login form. I’m using the login form from the default ASP.NET MVC 2 template (located at Views/Account/LogOn.aspx). Notice that it is based on a model of type Demo.Models.LogOnModel (located inside Models/AccountModels.cs).
The Web Forms View Engine
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Demo.Models.LogOnModel>" %>
<% using (Html.BeginForm()) { %>
<%: Html.ValidationSummary(true, "Login was unsuccessful.") %>
<div>
<fieldset>
<legend>Account Information</legend>
<div class="editor-label">
<%: Html.LabelFor(m => m.UserName) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(m => m.UserName) %>
<%: Html.ValidationMessageFor(m => m.UserName) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(m => m.Password) %>
</div>
<div class="editor-field">
<%: Html.PasswordFor(m => m.Password) %>
<%: Html.ValidationMessageFor(m => m.Password) %>
</div>
<div class="editor-label">
<%: Html.CheckBoxFor(m => m.RememberMe) %>
<%: Html.LabelFor(m => m.RememberMe) %>
</div>
<p>
<input type="submit" value="Log On" />
</p>
</fieldset>
</div>
<% } %>
Razor
@model Demo.Models.LogOnModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(true, "Login was unsuccessful.")
<div>
<fieldset>
<legend>Account Information</legend>
<div class="editor-label">
@Html.LabelFor(m => m.UserName)
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.UserName)
@Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="editor-label">
@Html.LabelFor(m => m.Password)
</div>
<div class="editor-field">
@Html.PasswordFor(m => m.Password)
@Html.ValidationMessageFor(m => m.Password)
</div>
<div class="editor-label">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
<p>
<input type="submit" value="Log On" />
</p>
</fieldset>
</div>
}
Spark
<viewdata model="MvcApplication1.Models.LogOnModel"/>
# using (Html.BeginForm()) {
${Html.ValidationSummary(true, "Login was unsuccessful.")}
<div>
<fieldset>
<legend>Account Information</legend>
<div class="editor-label">
${Html.LabelFor(m => m.UserName)}
</div>
<div class="editor-field">
${Html.TextBoxFor(m => m.UserName)}
${Html.ValidationMessageFor(m => m.UserName)}
</div>
<div class="editor-label">
${Html.LabelFor(m => m.Password)}
</div>
<div class="editor-field">
${Html.PasswordFor(m => m.Password)}
${Html.ValidationMessageFor(m => m.Password)}
</div>
<div class="editor-label">
${Html.CheckBoxFor(m => m.RememberMe)}
${Html.LabelFor(m => m.RememberMe)}
</div>
<p>
<input type="submit" value="Log On" />
</p>
</fieldset>
</div>
# }
NHaml
- using (Html.BeginForm())
=Html.ValidationSummary(true, "Login was unsuccessful.")
%div
%fieldset
%legend Account Information
%div.editor-label
=Html.Label("UserName")
%div.editor-field
=Html.TextBox("UserName")
=Html.ValidationMessage("UserName")
%div.editor-label
=Html.Label("Password")
%div.editor-field
=Html.Password("Password")
=Html.ValidationMessage("Password")
%div.editor-label
=Html.CheckBox("RememberMe")
=Html.Label("RememberMe")
%p
%input{type="submit" value="Log On"}
Conclusion
This was a quick comparison of the most basic features of the web forms view engine, Razor, Spark and NHaml. As you could see, they all support the same things but each takes it to its own direction.
Which one did you like the most?
All the best,
Shay.