SubSonic And MVC: Introducing Makai
One of my main responsibilities at Microsoft is to help build out the developer love around ASP.NET and ASP.NET MVC using SubSonic and other contributions (like the MVC Toolkit). I’ve been having a lot of fun working on SubSonic over the last year and some, and it gets more and more fun as the new MVC framework emerges from the CTP crib.
I’ve been sort of quiet about what I’ve been doing, and it’s mostly to avoid confusion with all the offerings coming out surrounding MVC (such as David Ebbo’s amazing Dynamic Data Controls).
Now that MVC is sinking into the ASP Developer Consciousness, I figure it’s time to let you know what I’ve been doing with SubSonic’s MVC cousin (dubbed Makai), and all the goodness that you can play with soon (no, I don’t know when
.
The Vision
In everything, SubSonic is here to fill the gaps, and send you home early. My goal with Makai is to give you a set of tools (and more, which I’ll write on later) that will help you to crank out your application quickly so you can get home and watch American Idol with your wife/partner/friends/animals.
In everything, we focus on time as value and the idea that less code is better code
“Makai” means “towards the ocean” in Hawaiian, and as I build this toolset out, I imagine that’s where you’re headed when you get done with work while the Sun’s still up.
The Scaffold, Reborn
Our “money maker” has always been the scaffold control – you just pop a declaration on a page and you’re off and editing. We’ve done the same for MVC, but in this case it’s a controller:
By creating a ScaffoldController for Northwind.Product, you have a complete editing suite (with no views to manage):

This list comes complete with search, sorting, and server-side paging. Also note that the foreign-key columns show up as they should, and every column is formatted properly (currency symbols according to culture, right-aligned numeric fields, checkboxes for boolean fields).
You might be wondering “how do you know what field to search on, and moreover link on in the scaffold list page”? The answer here is that we don’t – we guess and then tell you “well it’s our convention to x, y, z” if we’re wrong
. We’ve introduced a new property to the underlying schema (the layer that marries your object with your database schema) called Descriptor. This property is used all over the place and is the descriptive column for each record (like Product Name might describe a product in terms of a name). Our convention here is to use the first string field after the Primary Key – that’s what we link on, and that’s what we search on in the scaffold (using a fuzzy search).
The editor is pretty much the same as always, with the new addition of jQuery:

You also might be wondering if every scaffold will have our logo there, and the answer is yes – it will. Until you change the underlying template…
Templates
MVC is interesting in that it’s insanely flexible in terms of how you want to do your UI. It’s so flexible, in fact, that at some points you might feel lost (like I did) in terms of “how to do it right”.
I like the way Rails does it’s scaffolding – it generates a ton of code for you and you manage it from that point on. This is pretty efficient, but in many ways violates their premise of “Don’t Repeat Yourself” if you consider how much HTML and UI bits are generated over and over for each table. Rather than get in a Rails debate – let me just cut to the chase and explain how I’ve handled this for ASP.NET MVC.
We store all the UI HTML in template files, saved as Resources in the Makai dll. They are pulled only once, and then stored in memory (cached) for use each request thereafter.
A template looks like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <style> $style </style> <html> <head> <title>$title</title> </head> <body> <div id="pageheader"> <div style="padding-top:10px" > <img src="http://subsonicproject.com/images/subsonic_logo.png" /> </div> </div> <div style="padding:20px"> $contents </div> </body> </html>
This is our “Master” template, the thing that wraps the scaffold with our logo. We also have a CSS styles template that gets injected in the $style flag, and all the contents get injected in $contents.
The List page of the scaffold looks like this:
<h1>$title</h1> <form action="$searchaction" method="get"> <fieldset> <legend>Search by $descriptor</legend> <input type="text" name="q" size="50" value="$query"/><input type="submit" value="go" /> </fieldset> </form> <div> $message </div> $table <input type="button" value="New" onclick="location.href='$newlink'" />
They are very lightweight, and indeed I’ve tried to make them as modular as possible so you can overwrite them as needed. Which is the important part here.
You can override any template we have by creating the same-named template and sticking it in App_Data/Templates. All you need to do is keep the same directory structure and we’ll find it, overriding the one stored in our DLL.
For example – the editor page above outputs each editor row like this:
<div style="padding-bottom:10px"> <label for="$name"><b>$label</b></label><br /> $control </div>
If you like a table-based approach, you can create a new template at App_Data/Templates/Editor/EditorRow.htm and replace this HTML with whatever you like:
<tr> <td><label for="$name"><b>$label</b></label></td> <td>$control</td> </tr>
Your output will then look like this (tabular format):

We have templates for everything, and I’m still working on this “Injection Model” so it can scale etc – would love to hear your ideas on the matter
.
The Fun Doesn’t Stop There – Or Why Extension Methods Aren’t Evil :p
The core of scaffolding is to create a “skeleton” from which to build on. Other frameworks do this by generating the code for you that you then maintain. I’ve taken a different tack on this (but we’re still going to let you do this) and made the scaffold the result of all of our new Extension classes for SubSonic; so in essence you can “part out” the scaffold and use the dynamic pieces you like, from the entire editor right down to the individual control.
The scaffold you’ve bee looking at is the result of the following Extension Methods (among others):
- Product.Table.Schema.ToEditor() – creates an editor (based on templating) for an ActiveRecord object. This can also be accessed from ViewData as “CreateEditor<Northwind.Product>()”. You can suppress the fields that show up if you like as well. This editor uses the same rendering logic as the scaffold.
- Product.ControlFor(”ColumnName”) – creates the control that’s appropriate for the passed-in column. “ProductName” has a textbox, TextAreas for large text inputs, and (currently) jQuery’s calendar for all date inputs.
- Product.ToEditorRow(”ColumnName”) – same as the ControlFor() method, but this outputs a label as well (according to your template).
As I hope you’re seeing – having templates is a nice way to “skin” the very common controls that you write over and over again.
Each of these control methods accesses the data and populates each control accordingly. They also name the control properly so you can work with the MVCToolkit to update the data using UpdateFrom().
Membership
We also have a nice MembershipController that you can inherit from:

By inheriting from this controller, you can now work with your membership bits (again, no views with this one – all templated resources):

Editing a member:

Roles Management:

Summary
There’s a lot more to write about here, but I’ll wrap it up for now until there is something more concrete to show. I’m working hard to get SubCommander in synch with MVC so you can use its generator features to do many of the MVC fun stuff
Tags: MVC







