The Weekly Source Code 30 - Spark and NHaml - Crazy ASP.NET MVC ViewEngines
I've been getting more and more interested in how folks extend their applications using plugins and things. In my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you thirtieth in a infinite number of posts of "The Weekly Source Code."
Spark
I'm really enjoying the extensibility points in ASP.NET MVC, but not as much as some people. Spark is a really promising ViewEngine from Louis DeJardin. You can download Spark here and join the mailing list here. Not only is it promising, it's also freaky. Freaky in that good, makes-you-think way.
Louis says "The idea is to allow the html to dominate the flow and the code to fit seamlessly." When he says HTML should dominate the flow, he's not kidding. Check this out:
<ul>
<li each='var p in ViewData.Model.Products'>
$p.Name; $Html.ActionLink[[ProductController]](c=>c.Edit(p.Id), "Edit");
</li>
</ul>
See the "each" attribute on the UL? Freakly. ;)
Remember this is NOT WebForms. That <li> and the each attribute are not controls, or parts of controls or runat=server or whatever. This is a complete ViewEngine. It's a templating language in and of itself. (As are most ViewEngines, although it's not an obvious point to a lot of folks getting started with ASP.NET MVC or any MVC Framework)
That means that Louis has complete control of what the syntax is, and as you can see, it's somewhere in between HTML and Something Else. He's still changing the syntax based on feedback, so this is your chance to get involved.
Here's Louis' Northwind "Listing By Category" page:
<viewdata
model="IList[[Product]]"
CategoryName="string"/>
${PageTitle(CategoryName)}
<CategoryMenuItems category="ViewData.Model.Select(p=>p.Category).FirstOrDefault()"/>
<ul class="productlist">
<var styles='new[] {"odd", "even"}'/>
<li each="var product in ViewData.Model" class="${styles[productIndex%2]}">
<ProductImage style='"float:left;"'/>
<p>
<a href="/Products/Detail/${product.ProductID}">${product.ProductName}</a>
<br />
Price: ${String.Format("{0:C2}", product.UnitPrice)}
<span class="editlink">
(${Html.ActionLink[[ProductsController]](c=>c.Edit(product.ProductID), "Edit")})
</span>
</p>
<div style="clear:both;"></div>
</li>
</ul>
Notice not only that the iterators live on the markup tags like <li> but also that you can create variables. See how an array called styles is created to hold the strings odd and even, then used to set the class on the <li> on the next line. The "jump into code block" is usually ${ } rather than <% %> which I find nice visually.
However, Spark is all about choice, so you can use EITHER ${ } or <% %>. Whatever makes you happy.
Also, check out the <CategoryMenuItems> tag. What's that? That's a partial view-file that gives you clean partial rendering.
If you have a partial view file that are starts with an underscore, then you can call that from a regular view using its name as a tag. You can see two partial view files in the screenshot at right. It's really just a really pretty syntactic sugar over include files. Neat though!
Go check out Spark and hear more at Louis' Blog.
NHaml
The deeply awesome Andrew Peters created NHaml (part of MVCContrib), an ASP.NET View Engine using the Haml syntax from Ruby. I've been showing Andrew's stuff as an extreme example of what a ViewEngine could look like.
For example, here's a standard "Listing by Category" page using the built-in WebForms ViewEngine, written using NHaml. Notice the lack of angle brackets. Notice that the UL tag never ends...it just leaves scope. The whitespace is significant. Haml users feel strongly about not repeating themselves, even in markup. They want "Markup Haiku."
#foo
- foreach (var product in ViewData)
- if (product.Category.CategoryName != null)
%h2=product.Category.CategoryName
- break
%ul.productlist
- foreach (var product in ViewData)
%li
= Html.Image("/Content/Images/" + product.ProductID + ".jpg", product.ProductName)
.productdetail
=Html.ActionLink(product.ProductName, "Detail", new { ID=product.ProductID })
%br
Price:
=String.Format("{0:C2}", product.UnitPrice)
%span.editlink
(
=Html.ActionLink("Edit", "Edit", new { ID=product.ProductID })
)
Other cool View Engines include Castle's Fork of NVelocity and Brail (in MVCContrib).
Related Links
- ASP.NET MVC - WebForms Unplugged
- The Weekly Source Code 20 - A Web Framework for Every Language
- MVCContrib and NHaml
- Spark MVC ViewEngine
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
Like they say, "Nothing is impossible. Not if you can imagine it. That's what being a
Working with ASP.NET MVC now and find the WebForms view engine very clunky and I was really wanting to switch to Brail (which I have used in the past with MonoRail), but Spark looks even better!
One thing I was wondering: what about performance? Webforms are compiled, even the markup is converted to response.Write and then compiled. If a view engine uses complicated syntax, is that parsed each time the page is requested? Or do view engine developers use compilation too? Perhaps you could write a post about that?
Thanks!
I wrote a post about it for a while ago and it's interesting to see how people don't like it and custom tags. Can read the post and comments here.
I've been trying to put together asp.net MVC, MVCContrib, Unity and NHalm but with no success. Have you or any or you, other reader, got this to work?
Best Regards, Bruno Figueiredo
in the end you either buy a ready HTML template or pay money to get one that suits you, get one of millions for free, or you'll do it yourself with the help of _excellent_ CSS/XHTML editors like Microsoft Expression Web or Dreamweaver is...
and in the end productivity is 10 times better with this tools (in design and structure) than with any concise and short invented language that NHaml is...
it is a nic toy, but where is the real world? Can't really get it, the View is for designers, and you've got hundreds of them skilled in CSS/HTML and Photoshop PSD to XHTMLs conversion.
going to read if I find something new and sorry for rant;)
I like NVelocity very much as well. Aspects of Spark are obviously inspired by that view engine and others, NHaml included. The indentation of #if/#for/#component/#end, and of the code-braces-in-aspx, is one of the major motivations behind such a markup-centric template language.
Also NVelocity has been dead since like 2003 unlike Java's Velocity, unless you count castle's fork of the project, which you can find here
I can see the use of Haml/NHaml cause it shortens the syntax of html (yay for the wrist friendly!), but usually most templating system causes an extra layer of parsing on top of a templating language(php/asp) without any valid reason to do so (smarty, nvelocity, expression engine, etc).
Comments are closed.