December 2013

Volume 28 Number 12

The Working Programmer - Getting Started with Oak: A Different Approach

By Ted Neward | December 2013

Ted NewardAs I discussed last time, the Oak project is a Web framework that incorporates dynamic aspects and approaches common to more dynamic-­language-based frameworks (such as Ruby on Rails or any of the various MVC Web frameworks in Node.js, such as Express or Tower). Because it’s based on the Microsoft .NET Framework and uses dynamic and Dynamic Language Runtime (DLR) parts of C#, Oak takes quite a different approach to developing Web applications from those used by the traditional ASP.NET MVC developer. For that reason, as you discovered last time, getting the necessary bits to do Oak development is a little more sophisticated than just pulling it down via NuGet.

Assuming that you’ve read the previous column (msdn.microsoft.com/magazine/dn451446), downloaded the bits, installed them, kicked off the continuous build sidekick and gotten the initial build running on your machine (in IIS Express, on port 3000, as you recall), it’s time to start working on developing in Oak.

Firing Up

If it isn’t running on your box, do a “rake” and “rake server” from a command prompt, just to make sure that everything is kosher. Then launch “sidekick” (if it isn’t already running), and open a browser to localhost:3000, as shown in Figure 1.

Oak Project Help Window
Figure 1 Oak Project Help Window

As the resulting tutorial implies, there’s a sort of breadcrumbs-style walkthrough to learn Oak. Before I get into it, though, take a quick look at the project structure, shown in Figure 2.

Oak Project Structure in Visual Studio Solution Explorer
Figure 2 Oak Project Structure in Visual Studio Solution Explorer

The seed project consists of two projects: the ASP.NET MVC project and the project with the tests for the solution. The MVC project is a traditional ASP.NET MVC app, with the added “Oak” folder containing the source files making up the Oak parts of the project. This makes it absolutely trivial to step through the Oak parts of the code during debugging, and, in the spirit of all open source projects, also enables local modifications if and when necessary. Currently, the project has no models, three controllers and just a couple of views. More important, because there’s not much by way of code here, the first request to the endpoint yields an error that no “Index.cshtml” (or similar) view exists. The Oak bootstrapper suggests two steps. First, you need to create two new types: Blog and Blogs, a collection of Blog instances. Calling the class “Blogs” gives you easy, convention-based access to the Blogs table in the database:

public class Blogs : DynamicRepository
{
}
// This is a dynamic entity that represents the blog
public class Blog : DynamicModel
{
  public Blog() { }
  public Blog(object dto) : base(dto) { }
}

Second, the HomeController needs some changes to be able to respond to different HTTP requests sent, as shown in Figure 3.

Figure 3 Responding to Different HTTP Requests

public class HomeController : Controller
{
  // Initialize the blog
  Blogs blogs = new Blogs();
  public ActionResult Index()
  {
    // Return all blogs from the database
    ViewBag.Blogs = blogs.All();
    return View();
  }
  // Controller action to save a blog
  [HttpPost]
  public ActionResult Index(dynamic @params)
  {
    dynamic blog = new Blog(@params);

Much of this will be familiar to ASP.NET developers. What’s strikingly different is that everything is typed as the C# dynamic type, not as Blog or Blogs instances. The Blog type itself has no fields or properties. The Blogs type—an aggregation of Blog instances—similarly has no code declared on it to insert, remove, list, replace or do any of the other operations commonly associated with collections.

A lot of this power comes from the dynamic-based Gemini library, a core part of the Oak project (and the subject of my August 2013 column, “Going Dynamic with the Gemini Library,” at msdn.microsoft.com/magazine/dn342877). Blog extends the DynamicModel base class, which essentially means you can program against it without having to define the model up front. Any field you reference on any given Blog instance will be there, even if you’ve never referenced it before. This is the power of dynamic programming. Similarly, Blogs is a DynamicRepository. As such, it already knows how to store and manipulate DynamicModel objects.

Even more interesting is that right out of the box, Oak knows how to store Blog instances to a SQL table (named, not surprisingly, “Blogs”). Not only will it create the database schema on first use, but it can “seed” the database with any startup data the system might need.

When you construct a Blog instance, it takes a dynamic object as a parameter. The base class constructor knows how to walk through any of the dynamically defined fields/properties on that object. Similarly, the Blogs instance will also know how to iterate through all dynamically defined fields/properties of a Blog instance. It will store them to the database (on the call to blog.Insert). It also knows how to retrieve a Blog instance from the database via the BlogId field. All of this is powered by the code in Figure 3; no additional model code is necessary—at least, not yet. (There are other things you’ll want there, but for now, it all just works.)

By the way, if you’re wondering what the @ operator is, remember params is actually a reserved word in C#. In order to use it as an acceptable parameter name, you have to prefix it with @ to tell the C# compiler to not treat it as a keyword.

Having modified HomeController.cs, the next step is to create an acceptable view, Index.cshtml, in a Home folder under the Views folder. This will display the results of the controller’s work, as shown in Figure 4.

Figure 4 Creating the View

@{
  ViewBag.Title = "Index";
}
<h2>Hello World</h2>
<div>

If this page came up successfully, you're doing well! Go ahead and create a blog (try to create blogs with duplicate names).

</div>
<br />
@using (Html.BeginForm()) 
{
  @Html.TextBox("Name")
  <input type="submit" value="create" />
}
@foreach (var blog in ViewBag.Blogs)
{
  <div>
    <pre>@blog</pre>
    <br />
    <div>
Almost there, you have comments listing; let's try to add one.
    </div>
    <br />
  </div>
}

On the surface, the view isn’t just another ASP.NET view. Again, the dynamic nature of the system comes into play. No Blog instance has defined a Name field on the Blog type, yet when the form at the top of the view is submitted, a “name=...” parameter will be passed in to the HomeController. This controller will then pass on that name/value pair in the @params variable used to initialize a Blog instance. Without any additional work on your part, the Blog instance now has a Name field/property on it.

Continuous Continuousness

By the way, if you’re playing the home version of this game and you saved these files, you’ll see something interesting happened (see Figure 5).

Growl Notification Showing the Build Succeeded
Figure 5 A Growl Notification Showing the Build Succeeded

First of all, a notification popped up in the lower-right corner. This is Growl at work. It’s giving you the green-light notification that the build kicked off by the sidekick app you launched earlier has succeeded. If it fails for some reason, the graphic on the left of the notification window will be red, and the console output will display in the notification. Second, if you look in the console window in which sidekick is running, it will be apparent what happened. The filesystem watcher in the Blog directory registered that a source file changed (because you saved it). The sidekick took that as a cue to rebuild the project.

Assuming the files are saved and the code was correct, hitting localhost:3000 again yields the new result, shown in Figure 6.

Oak Cannot Make Bricks Without Clay
Figure 6 Oak Cannot Make Bricks Without Clay

This time, Oak is trying to connect to a running SQL Server instance in order to fetch any data from that table (the Blog table). This is Oak automatically trying to manage the object-relation mapping (ORM) parts of the project on your behalf, and I’ll get further into that next time.

A Different Style

As you can see, using Oak definitely involves a different style of developing. At no point did you have to do anything more complicated in Visual Studio than open a file, change its contents and save the new version—and add a new file to the project. At no point did you ever kick off a build, run it from within Visual Studio, or open Server Explorer to create tables or kick off SQL Server scripts.

All those things are still available to you, should the need arise. Again, Oak is just a layer (and a fairly thin one at that) on top of the traditional ASP.NET stack. However, this layer permits a degree of rapid development and productivity similar to other more dynamic environments, without losing the things you like from the statically typed world.

There’s more to do with Oak, but that will remain a subject for future discussion.

Happy coding!


Ted Neward is the principal of Neward & Associates LLC. He has written more than 100 articles and authored and coauthored a dozen books, including “Professional F# 2.0” (Wrox, 2010). He’s an F# MVP and speaks at conferences around the world. He consults and mentors regularly—reach him at ted@tedneward.com if you’re interested in having him come work with your team, or read his blog at blogs.tedneward.com.

Thanks to the following technical expert for reviewing this article: Amir Rajan (Oak project creator)