Hanalei, Hawaii Tuesday, February 09, 2010

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.

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: scaffold_controller By creating a ScaffoldController for Northwind.Product, you have a complete editing suite (with no views to manage): product_list 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: scaffold_edit 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): eidtor_2 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: membership By inheriting from this controller, you can now work with your membership bits (again, no views with this one - all templated resources): member_list Editing a member: member_edit Roles Management: roles 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


Thomas Wagner - January 14, 2008 - I was wondering what had happened to your work after they shipped Paula Poulus' blinq thing. Personally I was looking forward ti SubSonic being the DynamicDataService.... All good things take time. TW
Willie Tilton - January 14, 2008 - The templates stuff looks cool, but instead of having the templates in the DLL wouldn't it be easier for a developer to create a project that puts all possible Templates into the App_Data directory for them? I would think this would make it a lot easier if I wanted to make a few small changes, as well as not have to go to a manual to look up which filename I need to use to override something that's in the makai dll. It would also give me a good start without again having to refer to a manual to see which $bits I'd have to put into my template to make everything work.
Rob Conery - January 14, 2008 - @Willie - thanks for bringing this up - I'm going to create a skeleton project that will do just this and issue it as a Project Template - yes indeedy.
Haacked - January 15, 2008 - You've been busy! :) It reminds me of the Dynamic Data Controls, but using a more NVelocity like templating approach.
Shawn Oster - January 15, 2008 - @Willie: Good idea on having the bits external, more self-documenting, easier to grasp. I learn by example and having everything open-faced makes discovery a lot quicker.

@Rob: Hey Rob, no fair teasing us about helping write unit tests for Query2 when most of the tests don't even seem to pass, at least without some column called Neep :) What exactly was column 'Neep' anyway? Anyway they're going to have to clone you soon with all these good bits that you keep coming out with, or at least get you an intern to write docs for all of this goodness! I've also got to ask if migrations have been back-burnered or if they still fit in anywhere in the grand scheme of things? Oh, and how does this mystery SubStage fit into all of this goodness?

Lastly just wanted to say don't get too caught up in layering on the scaffolding butter and extensions creme, not because we don't love them but because part of what turned WebForms into the plump lipsticked-pig was this desire to make everything automatic and easy even for 101 level programmers. Personally I'd rather have fewer, simpler, clean things rather than a huge slew of whiz-bang features. Also one thing to remember is that pretty much only Rails new-comers use scaffolding, it's sorta considered training wheels for the newbie.

Anyway, the point is, I love everything you're doing but don't get too fragmented with all those great ideas, perhaps some focus in just a few areas might get us an actual release of some stuff vs. a ton of teasers :)
Rob Conery - January 15, 2008 - @Shawn - most of the tests don't pass? Neep? You got me there - if you can put this up on the forums, that would help. Nope - migrations are still on the front burner. Me, caught up? Hrrmph :p. One thing I'm able to do is see what works, and what doesn't. Agreed on the layer cake pig stuff, but at the same time working with data is very important. The scaffold bits are just "composites" of the main control set - the focus is on these far more than the scaffold as a unit. In terms of getting fragmented - that happened long ago :).
mike - January 15, 2008 - Maybe you can redevelop the web site administration tool that you can use in Visual Studio. It seems your templates are already better looking and more user friendly.
Allan - January 15, 2008 - This is good stuff, Rob. I was actually _this_ close to starting to modify the scaffold to do some of the stuff you're talking about here. I do think there's a role that scaffold-like controls can have in building out a complete app (not just for entering developer-data). Good validation support (IE using controller based validation rules somehow) would be awesome but that would presumably be tightly bound to a specific validation pattern and I'm not sure if that's really something that fits into the subsonic framework. Is that something that's been discussed? Also, Theming support would be nice, and would open up a number of options for customizing the scaffold gui bits.

Nice to see the direction all of this is going.
Troy Goode - January 15, 2008 - Hey Rob, This looks fantastic! Will the Membership controller feature login, registration, forgot password, etc forms? I know this is just a sneak preview, but I only see admin functionality in the screenshots above. Troy
Shawn Oster - January 15, 2008 - @Rob Conery: I actually did put this up on the forums on 1-11-2008, here (scroll to my last post):

http://forums.subsonicproject.com/forums/t/2439.aspx

Also I noticed another forum post with another user having the same issue. When I do a fresh checkout of subsonic from subversion the products.cs has a "Neep" column. Just do a Find in All Files for Neep and you'll see it. Obviously this has to be on a fresh checkout, no fair re-generating the DAL since that's where the problem is.
Danny - January 15, 2008 - REALLY nice work Rob. I'm very excited to see Makai in action. I've already been playing around with the MVC Framework and have really enjoyed it so far. Thanks for the update!
kevin - January 15, 2008 - Looks great rob. def agree with HAACKED in regards to nvelocity. I think having SubSonic and SubCommander for that matter generate the templates for List, View, Edit, Create would be killer. I'd also like to see the ability to generate anything via subcommander...user controls, etc. Essentially, creative freedom over the output. long day, early morning, so I hope I'm making sense.
Robin Massart - January 16, 2008 - Excuse if this information is available elsewhere, I haven't followed Subsonic so much recently. Is "Makai" available for download somewhere? Is it open source? Is it a MS codename for a future tool? But this looks like great stuff. Thanks, Robin
dietrich - January 16, 2008 - An observation on scaffolding: Rails 2.0 actually takes a step away from the concept of scaffolding. At first I thought that was crazy. But after using the helper "form_for" in a restful file structure, its so insanely easy to use that it almost makes scaffolding an unnecessary step. And I think it's possible to argue that scaffolding actually acts as a diversion from moving forward in a project because we get comfortable to the scaffold and then try to force fit the scaffolding into the project. A thought... --Dietrich PS Rob: The query tool looks great. Amazing you wrote that over Christmas....And very time you say the word "jQuery" I think maybe MS isn't evil incarnate :)
Steven Harman - January 17, 2008 - @Robin Massart, Since Rob is still sleeping (it's like 4:00am there) I'll step up and answer the questions I can. >> Is Makai available for download somewhere? Not yet, but it will be. We're still fleshing out exactly where we want the project to go and trying to get a solid codebase together as well as getting a CI server up and running. >> Is it open source? Indeed it is... err, will be? I guess it's not technically open until it's been released, right? :) >> Is it a MS codename for a future tool? No. The name is Rob's doing. And as he said earlier in this post
"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.
Hope this helps!
Nishan - January 18, 2008 - Great...

I think I will be able go home early. May be company will employ a junior developer and send me home.

Because its they don t need me
General - January 21, 2008 - Great article.
How about throwing in a
General - January 21, 2008 - whoops that enter key was in the wrong place at the wrong time ;-)

So how about throwing a unit test of mvc / makai / subsonic (slash meaning and/or) on the web ?
Just to get us started...

Thx for your thoughts.
OmegaSupreme - January 26, 2008 - This is so cool, a far superior way to develop. The time I've spent having to make all these lists and forms over the years... And you know I'll be like "yeah boss all these forms is going to take quite a while..." Muahahaha fool it's easy :D
Elmar - February 2, 2008 - Hi Rob, really looking forward to all this MVC goodnes. Especially the new Scaffolding-System which will add a lot of value for developers. Will Makai be (in) the "next" version of SubSonic or do you plan for a forked version of SubSonic? All the best, Elmar
runxc1 - April 14, 2009 - Any update on this Makai thing... Subsonic 3.0 perhaps?
robconery - April 14, 2009 - It's been scrapped - the MVC team took care of this with T4 and tooling. I'll write a followup post on this...
Steve - May 16, 2009 - Did you ever get that followup ?
Gecko