Several people have asked me what the difference is between Simple.Web and Nancy, so I’m going to try and outline it here, and share some more of my motivation for writing Simple.Web in the first place.
To start with, I don’t think there’s anything wrong with Nancy; I have a huge amount of respect for what Andreas and Steven have done and continue to do. It’s a great framework, and I’m really not setting out to compete with it. The thing is, they have their own roadmap and priorities, and I needed some things right away for my new project (which will be launching in the next couple of days; watch this space). Those things are not trivial, and I wouldn’t know where to start contributing them to that project.
With Nancy out of the running, my plan was to use ASP.NET MVC 4 and what was, at the time, WCF Web API. Those supported the two key features I want: async support in both, and content negotiation in WCF Web API. But in the transition from the WCF moniker to ASP.NET, Web API changed drastically. Suddenly, we had an ApiController base class, and worse, an opinionated focus on a distorted view of what constitutes REST, with an emphasis on HTTP methods (e.g. GET, POST) and a loss of flexibility around URIs. When I migrated my code to the new ASP.NET packages, everything broke and I couldn’t see a straight-forward way to fix it.
I also looked at FubuMVC and OpenRasta, but I’ll be completely honest: they confused the hell out of me.
Meanwhile, I’d been going to a lot of conferences and sitting in a lot of talks about designing proper RESTful APIs, using hypermedia and discoverability and suchlike, and I had some ideas rattling around my head for things to make that easier. When I read a blog post (which I have since been unable to find again) about Rails-style MVC being a violation of the Single Responsibility Principle, the final piece clicked into place and I went from some loose ideas to a fully-fledged concept, and suddenly I needed to write it to see if it worked.
Nancy in a nutshell
Nancy started out as a .NET implementation of the Ruby Sinatra gem. Sinatra is the anti-Rails: it’s incredibly small and light, really more of a DSL than a framework. Fundamentally, it’s a very efficient way of attaching behaviour to URIs. Despite having to work within the constraints of a strictly object-oriented language, Nancy manages the same thing. Applications are defined in modules, and anonymous functions are assigned to URIs within the constructors of module classes. If C# allowed code to exist outside of methods, or methods to exist outside of classes, I have no doubt that Nancy would be even more like Sinatra. (There is an F# package called Frank which gets closer.) Much of my involvement with Nancy stemmed from the fact that it went beautifully with Simple.Data, which has a similar “low-ceremony” solution to the ORM problem. Like Simple.Data, Nancy makes use of the dynamic type support in C# 4.0 to allow easy handling of things like query string parameters. There is an emphasis on your code, which is a thing I may often be heard saying is important.
Simple.Web in a nutshell
Simple.Web is a ground-up implementation of the single-action controller pattern, which already has some currency in the MVC world. Many developers will create a separate controller for each URI, with a single action, and all the supporting methods and so on contained in that controller. But with a framework like ASP.NET MVC, you still have an Action method which returns an ActionResult, and the only other things which may be inferred about the action are the parameters, and anything you can specify in a method attribute. By enforcing the one-class-per-URI pattern (I call it “Model-View-Handler”), Simple.Web allows interfaces to be used as part of the equation, and that opens up far more possibilities than I had realised when I started writing it. So Simple.Web doesn’t use dynamic types at all (except for dealing with a design-time glitch in Razor that I haven’t worked out yet). Instead, it uses a ton of reflection and code-generation to work within a statically-typed paradigm.
With all that said, let’s look at the key differences between the two frameworks. I’m not making any value judgements about anything here, and as I’ve already said, the two things I needed which are in Simple.Web are in the roadmap for Nancy.
- Nancy is driven by a diverse community who want different things, and Andreas and Steven work hard to supply them. Simple.Web, at the moment, is mainly driven by what I need for the thing I’m making. Some examples:
- Nancy supports a load of different view engines. Simple.Web supports Razor.
- Nancy makes an effort to run on Mono. Simple.Web happens to, and I do want it to, but it’s not the primary concern for me at present.
- Nancy has high-level support for things like different types of authentication and validation. Simple.Web provides one low-level hook for authentication, and has no built-in support for validation.
- Nancy supports multiple hosts, including self-hosting. Simple.Web is only fully tested on ASP.NET and IIS, although it is OWIN-compliant, and seems to run OK on my little Flux server.
- Both frameworks support multiple IoC containers, but in my case this is because people have already contributed Autofac and StructureMap plug-ins to Simple.Web. Nancy also has an in-the-box IoC container, which Simple.Web doesn’t.
- Nancy gives you access to an HTTP context object for dealing with things like headers. Simple.Web tries to abstract that away into an extensible pipeline system, which is a complicated subject and will be the subject of a future blog post. The short version is, you get what you want out of the HTTP request context and into properties before your application code is called.
- Both frameworks are written with testability in mind. In the case of Nancy, there is a Testing package, which gives you a Browser class that you can use to set headers and so on. With Simple.Web, because the context is hidden away from your application code, you can instantiate a handler class and just set all the properties directly, so you don’t need to build query strings or headers or anything. Again, that will be covered in more detail in a future post.
- Nancy is much more terse than Simple.Web. If you want to, you can write your entire Nancy application in a single class, which need only derive from NancyModule. You can write a Nancy app in a tweet. In Simple.Web, you have to write a separate class for every URI, and although there is no base class, it has to implement interfaces for each thing it might do or need. You can declare your own base classes, though. You can’t write a Simple.Web app in a tweet.
- Conversely, Simple.Web is much more structured than Nancy. The static typing provides more information in the code, and enforcing a separate class for each URI can make team-working easier, since people are less likely to be editing the same file at the same time.
- Simple.Web supports Task-based asynchrony. The primary methods and the Output properties can all return Tasks, and the entire pipeline is asynchronous. If you’re using C# 5 (with .NET 4.5 or 4.0) you can use the async and await keywords. Nancy has this on the roadmap; I don’t know the current status.
- Simple.Web supports content negotiation. This means that handlers return objects, and Simple.Web determines how to render them based on the client’s request (in particular, the Accept header). This includes deciding whether to render HTML for a browser or a data format like JSON or XML for an API call. (A side-effect of this is that the View declares which handler it is for, instead of the other way around.) Again, Nancy has content negotiation on the roadmap, but at the moment, you return a specific content type from your method.
- Simple.Web has some features designed to make it easier to build proper RESTful APIs, with links automatically included in JSON and XML data based on metadata in attributes. You absolutely can build a proper RESTful API in Nancy, but it’s not quite first-class in the same way.
- Nancy has much, much more documentation and community support than Simple.Web (although there is some documentation).
Simple.Web and Nancy are two very different solutions to similar, but not identical, problems. Nancy is brilliant for getting a web site up and running quickly, with a minimal amount of code, and with a lot of choice, particularly around view engines. Simple.Web is great for building RESTful APIs and services, and supports content negotiation and async.
I have not set out to compete with Nancy, or with any of the other open-source frameworks in this space. We’re all competing with ASP.NET MVC, WebForms and Web API, and I think that’s a good thing to be doing. Choice is good.