OdeToCode IC Logo

Client Rendering Views with Spark and ASP.NET MVC

Thursday, March 12, 2009

Spark is a view engine for the ASP.NET MVC and Castle Monorail frameworks. I’ve been wanting to try this creation by Louis DeJardin for some time, but ScottW pushed me over the edge with “If you are using ASP.Net MVC, you owe yourself to spend some time with Spark”. The Spark documentation makes it easy to get started, and the source code and examples are even more valuable.

There are quiet a few tutorials for Spark floating around, but I wanted to call out what appears to be a well hidden secret in the samples: the client rendering of views. In short, the client rendering produces JavaScript you can invoke on the client to render the same HTML you see when rendering a server-side partial view. This means you can happily fetch JSON from the server and use it to produce HTML without duplicating the server-side template logic on the client.

As an example,let’s say you have the following partial view to render the employees inside a department:

<div id="employees">
  <table>
    <tr>
      <td>ID</td>
      <td>Name</td>
    </tr>
    <viewdata department="Models.Department"/>
    <tr each="var employee in department.Employees">
      <td align="right">
        ${employee.ID}
      </td>
      <td>${employee.Name}</td>
    </tr>
  </table>
</div>

Notice how in Spark you can weave C# into the markup without breaking the flow of the HTML.

Next, let’s say you wanted the ability to refresh just this partial section of your view by asynchronously fetching data from the server. A first step would be to create a controller action that returns a Spark JavascriptViewResult.

public ActionResult ShowEmployees()
{
    return new JavascriptViewResult {ViewName = "_ShowEmployees"};
}

This action tells Spark to generate some JavaScript code from the _ShowEmployees partial view (the one we see above). The JavaScript will know how to create the same HTML as the server side view. Since this action produces JavaScript, you'll want to add a <script> in your main view that references that action endpoint. (this is reminiscent of how ASP.NET AJAX produces WCF proxies in JavaScript that know how to invoke service endpoints on the server, except client rendering isn’t about services – it’s about sharing a data binding template logic between the client and server).

<content:head>
...
<script type="text/javascript" src="~/Department/ShowEmployees"></script>
</
content:head>

What you’ll receive in your view is a JavaScript object with a RenderView method, and the RenderView method knows how to take your view model (as JSON data) and create the same HTML as the server-side partial view. Combining this generated JavaScript object with jQuery’s AJAX capabilities is straightforward.

$.getJSON(
  "/Department/Refresh/" + $("#id").val(),
  function(data) {
    var content = Spark.Department._ShowEmployees.RenderView(
                     { department: data });
    $("#employees").html(content);
});

The above code gets a JSONified version of your view model from the server and passes it into RenderView. RenderView returns the HTML we can use to update the UI. Clever!

For more on Spark, check out Lou’s blog.