The Weekly Source Code 30 to be specific, by Scott Hanselman.

I’ve been followed Hanselman now for a while and had the opportunity to see him in person at mix08 presenting a session on Asp.Net MVC. He’s a funny guy and a great speaker.

So that’s pretty cool. I’m glad he liked how Spark came together.

There are a bunch of updates related to Spark so I think I’ll just run through them in whatever order.

First, the documentation and downloads area have moved to a Drupal cms at http://dev.dejardin.org instead of using the Trac site’s built-in wiki.

There’s a new release of Spark view engine available on the download page.

The first thing to watch out for is a breaking change: support for the $expression; syntax has been removed due to collisions with normal prototype and jquery usage. Anyplace that was using that syntax will need to change to ${expression} but beyond that any valid csharp expression still works to produce output.

Another requested change from Tim Schmidt has been made to support single-quoted string literals when csharp appears in a spark file. That’s to allow xml attributes to use double quotes even though they contain expressions. For example, the code below that writes out a string if a product is in stock:


<ul>
  <li each="var product in Products"
    class="${product.Quantity != 0 ? 'instock' : 'outofstock'}">
      ${product.Name}
  </li>
</ul>

The quotes are changed when the generated class is produced. The generated class contains the following:


Output.Write(product.Quantity != 0 ? "instock" : "outofstock");

An even more significant enhancements has been made to the conditional syntax. This is based on some excellent feedback and ideas from Pablo Blamirez a few weeks back.


<test if="!user.IsLoggedIn">
  <p>Please sign in.
    ${Form.FormTag(new {controller="account", action="login"})}
    user ${Form.Textbox("user")} pass ${"you get the idea..."}
    ${Form.EndFormTag()}
  </p>
  <else if="user.IsAdministrator"/>
  <p>Administrator ${user.Name} etc.</p>
  <else/>
  <p>Hello, ${user.Name}.</p>
</test>

Note the empty <else/> elements. The previous formats are still supported, so you could use <if condition=""> instead of <test if=""> and the else elements may also be used in a way where they follow the original test. So the following is equivalent.


<test if="!user.IsLoggedIn">
  <p>Please sign in.
    ${Form.FormTag(new {controller="account", action="login"})}
    user ${Form.Textbox("user")} pass ${"you get the idea..."}
    ${Form.EndFormTag()}
  </p>
</test>
<else if="user.IsAdministrator">
  <p>Administrator ${user.Name} etc.</p>
</else>
<else>
  <p>Hello, ${user.Name}.</p>
</else>

In the end it’s a stylistic preference.

I have a buddy using Spark on a project and there are some things he was excited to show me earlier today. I asked him to email me an example so I could put up a post about it. It’s especially relevant because earlier in the week a question came up about a case where threaded comments were being rendered in a recursive collection. This is the same type of situation.

A <macro> element in Spark is used to add a function to the generated class. Inside the macro all of the html and output is captured and the function returns it as string. So it can be used in an ${expression}. The function can also call itself, as you can see below.


<viewdata clusterList="List[[Cluster]]" />

$Form.FormTag(new {method="get"});
<p>
  $Form.LabelFor("topic", "Topic:");
  $Form.TextField("topic");
</p>
$Form.EndFormTag();

<style>
    ul.cluster { margin-left:25px; }
</style>

<p if="clusterList != null">
    $displayClusters(clusterList);
</p>

<macro name="displayClusters" clusters="List[[Cluster]]">
    <ul class="cluster">
        <for each="var cluster in clusters">
            <li>$cluster.Name;</li>

            <if condition="cluster.Clusters != null">
                $displayClusters(cluster.Clusters);
            </if>
        </for>
    </ul>
</macro>

This is using the MonoRail version of the Spark view engine of course. You can tell by the use of the Form helper. But that’s a cool example of building a ul-nested li tree where the function string displayClusters(List<Clusters> clusters) is calling itself.

Also note the use of the anonymous type used as an option dictionary in the new {method="get"}. Very nice.

I’m installing a vmware guest for a particular role and I need Windows SDK installed. It’s a 1.4 gb iso file - not a problem. It’s downloaded to a local \install directory (a habit I’ve formed when installing anything that’s downloaded).

The next step, to mount the iso as a virtual cd, is very easy. The host o/s can mount any iso on the virtual cd drive of the guest o/s but first I need to copy the iso from the guest to the host drive. And my Zen moment of introspection is when I think: I’m connected to a virtual machine. I’m about to open a UNC location on the real machine which is hosting this fake machine in order to copy a file I just downloaded. So I’m copying a file onto a real drive from a fake hard drive which itself actually exists as files on that real drive I’m copying to.

Since I have explorer open I point it to to the unc location of the virtual drive on the host o/s. So my guest o/s is now displaying to me, as if it was network files, the actual files inside which exists everything that is currently running on guest o/s which has allowed me to view them.

Sort of like looking at a crystal ball that contains the universe and everything in it, including the observer and the crystal ball. A PC version of an out of body experience.

Computers just keep getting cooler.

Busy times

July 13th, 2008 1 Comment

Lots of things going on lately. Flew to NY and back in the past few days for a meeting at 1 World Financial Center building.


View Larger Map

Really interesting location. From one side of the building you can see Liberty Island, and from the other you can see the World Trade Center location.

Yes, yes. Blackberry cameras are really bad. You’ll just have to take my word for it - the vertical smudge is the statue which you could can see perfectly fine in person.

And on a positive note this trip is sort of a milestone. I’ve had a mild phobia of flying which I’ve never allowed to interfere with personal or professional travel. That is to say I’ve never declined the opportunity to travel for work because of it. But I have relied on a heavy regimen of airport bar Long Island Iced Teas pre-flight. This trip however marks the first time I simply drove to the airport, walked on a plane, and was either asleep or bored for the entire flight both ways. Yay.

Spark in practice

June 29th, 2008 No Comments

I have to say I’m really happy with how the view engine turned out. It’s being dog fooded on some prototyping at the moment and there are lots of things that I really appreciate as it’s going along.

Consider the following partial file that renders a tab strip followed by a number of pages. Each page has a number of items…

_MostPopular.spark


<div id="MostPopular">

  <content name="head">
    <link rel="stylesheet" type="text/css"
          href="${SiteRoot}/content/css/home-mostpopular.css"/>
    <script type="text/javascript"
            src="${SiteRoot}/content/js/home-mostpopular.js"></script>
  </content>

  <div class='header'>Most Popular</div>

  <ul class='tabs'>
    <var i="0">
      <li each="var page in mostPopularData.Pages"
          id='MostPopularTab${++i}'
          class='tab ${i == 1 ? "selected" : ""}'>
        <a href='#'>${page.Title}</a>
      </li>
    </var>
  </ul>

  <div class='pages'>
    <var i="0">
      <ul each="var page in mostPopularData.Pages"
          id='MostPopularTab${++i}Page'
          class='page ${i == 1 ? "selected" : ""}'>
        <li each="var item in page.Items.Take(5)">
          <a href="${item.AbsoluteUrl}">${H(item.Headline)}</a>
        </li>
      </ul>
    </var>
  </div>

</div>

Read the rest of this entry »

The folks at the Castle Project development list have provided some excellent constructive criticism and some new functionality was added to Spark as a result.

One thing which is new is the ability to inline code directly.


#int total = 0;
#foreach(var item in items)
#{
#   total += item.Quantity;
#}

#if (Params["page"] == "2") {
  <p>Second Page - total: $total;</p>
#} else {
  <p>Not the second page
#}

Or using the slightly more standard <% %> syntax


<%
int total = 0;
foreach(var item in items)
{
  total += item.Quantity;
}
%>

<%if (Params["page"] == "2") {%>
  <p>Second Page - total: <%=total%> </p>
<% } else { %>
  <p>Not the second page
<% } %>

Another question which came up was about the support for MonoRail ViewComponent classes. This was an especially interesting point because the view engine itself is written to be used in any framework, while the ViewComponent is very specific to the Castle Project. To make this happen the Spark parser and code generator was changed to call an extension factory interface as it processed the elements from the view templates it digested. This enabled the MonoRail-specific view engine library to recognize elements whose names matched those of the registered view components. It can then provide an extension that consume the contents of that element to write it’s own chunks of generated code at the appropriate point.

So the net result is support for things like this.


<p>blah blah blah</p>
<DiggStylePagination Page="SomeMessages" Adjacents="3">
  <prev>Go Back</prev>
  <next>Show More</next>
</DiggStylePagination>
<p>blah blah blah</p>

And another piece of functionality which was added was the ability to declare and use helper-like functions inside the template file.


<macro name="MessageBox" caption="string" message="string">
  #Logger.Info(message);
  <div class="msgbox">
    <h3>$H(caption);</h3>
    <div>$message;<div>
  </div>
</macro>

<p>blah blah blah</p>
$MessageBox("Warning",
  "You're about to change " + somearg + " permanently.");
<p>blah blah blah</p>

The thing that I think is pretty cool about that is how it create a function what works like a helper method, because it takes a handful of arguments and returns a string, but the body of this thing is declared in the template vernacular. So it can be very “view oriented” in how it’s build and maintained. Which makes sense for a lot of helper-style methods which are very much about the idea of concatinating and returning html - implementing simple helper methods in classes can occastionally put more html in your cs files than you’re comfortable with.

In any case I’m really happy with how the view engine has come together. It’s been a delightful experience, didn’t take much actual time, and has really reinforced for me the value of tools like resharper and practices like test driven development.

Between GTA IV and working on the Spark view engine my blogging time on nights and weekends has been nearly squeezed out of existence.

So in between “real” posts here’s a quick preview about what’s coming up… Some syntax from the Spark view engine soon to be available to Asp.Net Mvc and Castle Project MonoRail.

If you’re especially curious there are some version 0.1 docs that show syntax.

And here are some fragments from a monorail demo site for an example.

homecontroller.cs


	[Layout("Default")]
	public class HomeController : SmartDispatcherController
	{
		public void Index()
		{

		}

		public void Apply(string name, string address)
		{
			PropertyBag["caption"] = "Information submitted";
			PropertyBag["message"] = string.Format("Name {0}, Address {1}", name, address);
			PropertyBag["continue"] = new {controller="Home", action="Index"};
			RenderSharedView("common/simplemessage");
		}
	}

home/index.xml


<h1>Hello world</h1>

<div>
  $Form.FormTag(new {action="apply", method="get"});
  <p>$DateTime.UtcNow;</p>
  <p>Name: $Form.TextField("name");</p>
  <p>
    Address:
    $Form.TextField("address", new {@class="w00t", style="margin-left:20px"});
  </p>
  <p>$Form.Submit("Apply");</p>
  $Form.EndFormTag();
</div>

common/simplemessage.xml


<div>
  <h3>$H(ViewData["caption"]);</h3>
  <var link=’Url.Link("Continue", ViewData["continue"])’/>
  <p>$link;</p>
  <p>$H(ViewData["message"]);</p>
  <p>$link;</p>
</div>

shared/default.xml


<html>
  <head>
    <use namespace="System"/>
    <use namespace="Castle.MonoRail.Views.Spark"/>
    <title>Hello</title>
    $Ajax.InstallScripts();
  </head>
  <body>
    <div id="header">
    </div>
    <div id="main">
      <use content="view"/>
    </div>
    <div id="footer">
    </div>
  </body>
</html>

Zu Zu\'s bread friend

Zu Zu’s bread friend.

This is our dog which is least sane.

Dethklok

June 1st, 2008 No Comments

It’s been a little while since the last post.

The next techie one will be about the Spark view engine I’ve put together for Asp.Net Mvc. But the current geekie one is about Dethklok! The tour is coming to First Ave in Minneapolis and Brenda and I just bought tickets for it.

Dethklok is looking forward to ruining your hometowns. Brutal.

Gotta love Adult Swim.