Simple.Web

So on Wednesday at the Skills Matter Progressive .NET Tutorials, I gave a session offering an introduction to this new thing I’ve been working on, Simple.Web. The session was recorded, and you can watch it here if you like (it’s just over 3 hours), but I’m going to try and give a rough idea of what it’s all about in this post. I’ll be following this up with some more detail on specific areas in the coming days.

Why?

Obvious question, really. There are lots of web frameworks out there for .NET already, which all offer different things, so why build a new one? The primary answer is: none of them worked quite the way I wanted. There were things I liked about some of them, but not all in the same package. I loved WCF Web API while it was still called that, when Glenn Block was working on it, but by the time it became ASP.NET Web API it wasn’t the same thing any more. It’s had a Controller base class foisted upon it, for a start, and the routing was all completely different, and it broke my (current, start-up, commercial) project, which soured the relationship. I needed something else for my project, and nothing I knew of did the things I really needed right away.

The other thing was that I read a couple of blog posts around the theme that the MVC pattern breaks the rules of SOLID, most notably the Single Responsibility Principle. In a traditional MVC application, a Controller represents a resource type, and has Actions for all the possible operations against that type of resource: Create, Read, Update, Delete and so on. That’s multiple responsibilities right there. And this impacts on performance as well as maintainability, because you have to inject the dependencies for all the possible actions in the constructor, even though none of them may be needed. Search for “single action controller” and you’ll find dozens of posts warming to this theme and offering that workaround, but it got me thinking, what if all the controllers were single action? What if, instead of using a method to represent an action (or a URI), you used a class? How would a framework like that look?

Design goals

I decided to try building a framework like this in tandem with the commercial project, primarily focusing on getting it to do the things I needed it to do for that. My primary goals for the initial version were:

  • Keep it simple;
  • It should be ridiculously easy to do TDD and/or BDD;
  • Support asynchronous, non-blocking handling of requests;
  • Make it easy to build a proper RESTful, hypermedia-driven application and services, including supporting content-type negotiation for all requests, including HTML;
  • Be really open and extensible, because if people can write plug-ins and add-ons easily, I don’t have to build all that stuff in.

To that end, the framework has been built to be extensible, but currently provides a limited set of options. The only hosting option at the moment is on top of ASP.NET. The only view engine supported is Razor. It uses JsonFx for handling JSON, and a very rough system built on the WCF DataContractSerializer for XML. And the only IoC container I’ve built support for is Ninject. These are all personal preferences, and while I’ve tried to make sure they’re all abstracted in a way that will make it very easy for additional plug-ins to be built, I fully expect to have to make at least a few core changes if and when people want to build them. In particular, the work I did on refactoring out the hosting code into a separate project for ASP.NET probably took too much code with it.

Keeping it simple

I’ve tried to make everything obvious, and cut out boilerplate as much as possible. In particular, there are no base classes for handlers, although you are free to create your own if you want to. Everything is done through interfaces. Lots and lots of interfaces, each one very small, in accordance with the Interface Segregation Principle. Also, everything gets put together automatically, with no complex routing tables and brittle dependencies.

Facilitating TDD

The biggest barrier to automated testing of web apps is the need to fake, mock or stub the accoutrements of HTTP in order to fool the object under test into thinking that it’s running in a web server. In Simple.Web, handler objects know nothing about HTTP. They implement interfaces to tell the framework what information they need from the request, and what information they provide for the response. The framework takes care of mapping the various properties and methods to HTTP. This means a handler can be created and have those properties set in very simple “arrange” code, and you never need to mock another Request object in order to set a header or a cookie or a request body. Handlers can stick to implementing application and business logic, and you can stick to testing that logic, which is how it should be.

Building the handlers in this way has had other positive effects on the system and the code. It’s made for some very small, modular types; it’s made the HTTP<->handler mapping into an extension point which developers can hook into really easily; and it’s meant that the runtime system can be highly optimised, since all the information about what a handler needs and does is right there in its type declaration.

Supporting asynchrony

This is as important on a web server as it is on a client machine. In general, web servers spend most of their time waiting on I/O operations, pointlessly blocking on threads while a database or another web service does its thing. If this time spent waiting can instead be spent processing other requests, we can service more clients with fewer servers. This is, of course, the principle behind Node.js, but it turns out it works just as well in .NET, thanks to the Task Parallel Library and Windows’ kernel-level evented I/O. ASP.NET MVC 4 allows you to return a Task<ActionResult>, and when combined with the awesome new async/await features in C# 5, it’s really easy to write non-blocking web code.

In Simple.Web, the primary method on each handler is taken from the HTTP method represented by the handler interface. For example, a GET operation is handled by a type which implements the IGet interface, and that declares a Get method which returns a Status. It’s all very getty. Like this:

[UriTemplate("/")]
public class GetIndex : IGet
{
    public Status Get()
    {
        return Status.OK;
    }
}

Don’t worry about where the output comes from, we’ll come to that. The important thing at this stage is that for every HTTP method interface, there is an asynchronous variant, where the relevant method returns a Task<Status> instead, and that would look like this:

[UriTemplate("/")]
public class GetIndex : IGetAsync
{
    public Task<Status> Get()
    {
        return DoLongRunningThing()
            .ContinueWith(t => Status.OK);
    }
}

Except of course you’d have some error checking and stuff in there. That’s where you want to be using C# 5 and async/await, otherwise it’ll bake your brain.

The point is, the decision to make something asynchronous is not a big one, and you’re free to mix and match synchronous and asynchronous handlers in a project; it’s up to you.

REST and hypermedia

The most important feature for implementing good, flexible, robust web apps and APIs is proper content-type handling. This is one of the biggest problems with ASP.NET MVC: actions do not return resources; they return specific representations of resources. The action decides whether to render a view or some XML or some JSON, when in fact it should be the client telling the action what representation it’s after. To do this, you need a content-type negotiation system, so Simple.Web has one, although it’s in a fairly embryonic state at this point.

A Simple.Web handler outputs an object, or a collection of objects, and lets the content-type negotiation system work out what to do with it. If the client is a browser asking for HTML, then the view-engine system kicks in, and tries to find a view. It can do this using the @model directive if only one view in the application declares that model type:

@model Sandbox.Form
<!DOCTYPE html>
<html>
    <body>
        <div>
            <h1>@Model.Text</h1>
        </div>
    </body>
</html>

or, if that is not specific enough, or if there is no model type for a given handler, there is a new @handler directive to support directly linking between view and handler:

@handler Sandbox.GetForm
<!DOCTYPE html>
<html>
<body>
<h1>@Handler.Title</h1>
<form action="/submit" method="POST"><input type="text" name="Text" /><input type="submit" /></form>
</body>
</html>

This also results in the handler being a property in the view, with all its public variables available; no more need for ViewBags.

The other aspect to HTTP and hypermedia-based apps and APIs is that all resources should come with a complete, human- and machine-readable set of the available state transitions for the resource, represented as links. There is a system for building these links within Simple.Web, and I’ll be covering that in an upcoming post.

Be open and extensible

Over the last year and a half of maintaining Simple.Data, I’ve been really impressed by the can-do attitude of people who have built and maintained their own adapters and providers, and submitted code back to the core project when they needed something. There’s an astonishing number of databases, both SQL and NoSQL supported, and mostly that support is nothing to do with me.

I want to let the same kind of people do that with Simple.Web too, whether it’s for view engines, or hosting systems, or content-type handlers. And with a web framework, there’s an additional driver for being open and extensible, because there are plenty of points within a specific project where you might want to change the way something works.

So the framework comes out of the box with some plug-ins, which are included in the Simple.Web package for the time being for convenience, but I’m hoping that fans of other hosts/view-engines/serializers will pop up with their own alternatives, at which point I’ll separate out the JsonFx and the Razor, for instance.

But Simple.Web is extensible in smaller ways, too. For example, there are interfaces for GET, PUT, POST, PATCH, etc., but I haven’t created an interface for MERGE, which some systems use. What I have done is make it easy for you to add your own HTTP method interfaces, which will get picked up by the framework and integrated just like the built in ones. So you can add MERGE, or TRACE, or make up your own methods, like SMITE and BESTOW.

And then there’s all those interfaces which map information between the HTTP infrastructure and your handlers. Those are all built on a very simple pattern, using public types and attributes, and you can create your own interfaces which will get integrated into the pipeline in exactly the same way that the built-in ones do. If you have a custom header called X-User-Mood, you can create a “behavior” interface and some “implementation” code, and it will get hooked in for you, so you never need to pollute your handler code with HTTP contexts and requests and responses.

Getting started

OK, that’s enough waffle for now. If it sounds interesting, then the Skills Matter video has a lot more of me blathering on about it and doing some demos, many of which fail spectacularly. You can install the package from NuGet, or download the source from Github, where there is also a demo application which demonstrates some of the main features. There’s a Google Group for people who want to use the framework to build applications, and another one for people who want to build plug-ins or add-ons or contribute to the core in some way (hint: Razor needs some love).

Also, because this one is all statically-typed, with no dynamic oddness, IntellSense is your friend, and there are documentation comments all over the place so it should be reasonably easy to pick up. I’m looking into something that generates actual help from the comments and isn’t Sandcastle, so hopefully there’ll be a manual soon.

Finally, I’ll be putting up some more detailed posts about various features over the next few days and weeks, so watch this space.

Comments

  1. You need to get hooked up to http://owin.org.

  2. Did you give up on System.Net.Http? I scrapped my core fx for that and have rebuilt Frank around that core, which I find very testable and light. I agree about the Web Api controller approach, though. I use it, but I much prefer using HttpMessageHandler directly. Also you should get this on @loudej’s radar for the OWIN effort (http://owin.org/).

    • Didn’t really look at it on the server side, although I’ve been using it for client stuff in my app.

      Definitely want to get an OWIN hosting layer out there.

  3. Sounds really good that you built something around your own needs and uses

    Did you check out FubuMVC? It seems it can do a lot of the things you wanted. However I don’t know for sure.

    If I have any positive or negative feedback I’ll let you know when I’ve had a play.

  4. The google groups seem to require membership instead of being open for anyone. Other than that: Very interesting! I’m really pleased to see these kind of alternative approaches.

  5. Joseph Magly says:

    I like your concepts. I have been abstracting MVC using the Action/Executor Pattern (http://msdn.microsoft.com/en-us/library/cc984279.aspx) for a while. I only use controllers for a layer of routing. Your design removes the controller and promotes the action to a first class consumer of the request, this seems pretty compelling. I think I will take a deeper look at your framework.

  6. How well do you support F#?

    • I don’t really know, I guess it would work. Give it a try, and if there are ways it could be better supported please do let me know. I’m a fan of F#, I’d love Simple.Web to work well with it.

Trackbacks

  1. [...] Simple.Web – Mark Rendle reveals his latest project ‘Simple.Web’ a light weight framework which is friendly to TDD and BDD testing, supports async non-blocking request handling, does REST properly and is open an extensibile. Mark discusses the design goals, and how the framework works, along with sharing the video of his session at SkillsMatter’s Progressive .NET tutorial where he first revealed Simple.Web. [...]

  2. [...] extension SUPERSCROLLORAMA NDepend 4.0 Released Simple.Web – codeface Windows 8 Release Preview TShadwell/Horrible.js · GitHub Redactor WYSIWYG editor on jQuery Visual [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 3,742 other followers

%d bloggers like this: