Today I updated the CodeBetter.Canvas project to target the latest releases of NHibernate (2.1), FluentNhibernate (1.0 ) and Nhiberate Linq (1.0).
More importantly is the switch away from the MVC WebForms View Engine to the Spark View Engine. I've been learning and using Spark for the last month or so, and I'm a pretty big fan. I do think that you should strongly consider it for your next ASP.NET MVC project, it increases the readability and maintainability of your views, while being very easy to learn.
I think Spark is one of those love-it-or-hate-it kinda things, but I do think there are things anyone can learn from it. I would hate for ASP.NET developers to think that the default MVC view engine is the best (or even only) way to do things. Its good that Microsoft made the view engine pluggable, its great that developers might see new ways to mix layout and code.
I do worry that CodeBetter.Canvas is a little overwhelming from a learning point of view. If you've been doing .NET development the traditional way, then you'll have a lot of new technologies and patterns to learn (MVC, Spark, DI, Unit Testing, Mocking, jQuery and O/R Mapping). I do worry about this, but I can't imagine NOT adding a worthwhile feature like Spark for the benefit of those lacking the ambition and interest in improving their skill set. Some developers will suck it up and learn what they can, others will continue to fall behind - so be it.
As always, you can grab the source from Google Code
I do suggest that you check out the SparkViewEngine website for a great guide on setting it up and using it. You may also want to grab the latest source and use it instead of the 1.0 release (which is what Canvas is using) for the added caching capabilities which are excellent. However, I would like to show some Spark samples from Canvas to give you a quick idea of what it offers.
The first thing to take note of is that <%=XXX %> are gone, replaced with ${XXX}. I do find that this simple change does increase the readability a little, but the real advantage is that ${} will automatically HTML encode values thanks to the SetAutomaticEncoding setting of Spark set in the global.asax. If you don't want encoding, you use !{XXX} instead (you'll notice that Canvas uses both as needed).
You can pretty much look at Views/Shared/Application.spark to get a good feeling for what Spark is all about. This is the default master page layout used by all spark views (which can be changed or overwritten at multiple levels). First, you'll notice that we are declaring a variable, errors for use later on (more on this in a bit). You should also notice that we are defining a global variable, Title - which individual views can set to control the page's title (look a bit further down and you'll see that the Title variable is being outputted within our head's title tags).
Things get a lot more interesting with the <use> tags, which are equivalent to ContentPlaceHolders. Not only are they much more concise, but anything outside of an explicit content tag is automatically placed in the "view" placeholder. This helps reduce our code's nesting and the ASPX soup-tag. Given a simple master page of:
<body>
<use content="menu" />
<use content="view" />
</body>
Our view can simply be:
<content name="menu">
....STUFF...
</content>
<p>The main content doesn't have to be nested in a content element</p>
<p>Yay! it's a small but useful feature</p>
Next you might notice the <LoginLogoutMenuItem> and <PageData> elements. This is Spark's way to render a partial. Spark will look for a file named _LoginLogoutMenuItem.spark and _PageData.spark (in the shared folder, and in the controller's view folder) and render it out. What I like most about these is the ease with which we can pass information to our partial: simply add attribtes to the tag, such as (this is how the errors variable defined at the top of the layout is being used):
<SomePartial heading="'This Is A String Value'" products="Model.Products" />
Although there's a lot more to Spark, the last, and possibly coolest, feature is Spark's ability to embedded attributes within html elements and attributes. For example, one way to write an IF/ELSE is to use Spark's If/Else elements.
<if condition="Model == null">
<h3>No Results were Found</h3>
</if>
<else>
<table>
...do stuff
</table>
</else>
Another approach is to use the attributes on existing elements(which s much nicer with just an if):
<h3 if="Model == null">No Results were found</h3>
<table if="Model != null">...</table>
Even more impressive the embedding of the each attribute. Take a look at the old PageError partial versus the new one:
<%@ Control Language="C#" AutoEventWireup="False" Inherits="CodeBetter.Canvas.Web.ApplicationViewUserControl<string[]>" %>
<ul id="pageErrors">
<% Model.Each(e => { %>
<li><%=e %></li>
<% }); %>
</ul>
versus
<ul id="pageErrors">
<li each="var d in data">${d}</li>
</ul>
The same can be done at the attribute level, from the Spark documentation, take a look at how cleanly styles (or any other attribute) can be controlled:
<li each="var product in Products" class="first?{productIsFirst} last?{productIsLast}">
${H(product.Name)}
</li>
(as a bonus, the xxxIsFirst and xxxIsLast are automagically created by Spark when it sees the each attribute).
So, I hope that gets you interested in Canvas and in the Spark View Engine. There's a lot more to both free projects than what you see here. Canvas covers a broad range of technologies and patterns. Spark offers caching (and donut-caching), javascript integration, macros, batch compilation and more.
Posted
Tue, Sep 1 2009 6:49 PM
by
karl