Tuesday, 28 April 2015

One API, Four Frameworks: The Great .NET ReST Showdown

There’s only two hard problems in software: cache invalidation, naming things, off-by-one errors, null-terminated lists, and choice overload. Back when I started building data-driven websites, classic ASP gave you Request, Response, Application, Session and Server, and you built the rest yourself - and it was uphill both ways! These days, we’re spoiled for choice. Whatever you’re trying to achieve, you can bet good money that somebody’s been there before you. If you’re lucky, they’ve shared some of their code – and if you’re really lucky, they’ve built a framework or a library you can use.

Since the heady days of classic ASP, I’ve built quite a few systems that have to expose data or services to other systems – from standalone HTTP endpoints that just return true or false, to full-featured ReST APIs. I’ve come across several frameworks that are designed to help developers create ReSTful APIs using Microsoft .NET, each of which doubtless has its own strengths and weaknesses – and now I find myself facing the aforementioned choice overload, because if I was starting a new API project right now, I honestly don’t know which framework I’d use. Whilst I’ve got hands-on experience with most of them, I’ve never had the opportunity to try implementing the same API spec in multiple frameworks to compare and contrast their capabilities on a like-for-like basis.

So here goes. Over the next few months, I’m going to be developing the same API in four different frameworks, side-by-side. The APIs have to use the same back-end code – same data access, same business logic – and have to pass the same integration test suite. I’m going to start out really simple = “hello, world!” simple – and gradually introduce features like resource expansion, pagination, OAuth2, content negotiation. The idea is that some of these features will actually break the interface, so I’ll also be looking at how to handle API versioning in each of my chosen frameworks. I’m also going to try and respect the idioms and conventions of each of the frameworks I’m working with – good frameworks tend to be opinionated, and if you don’t agree with their opinions you’re probably not going to find them particularly helpful. 

The Frameworks

Microsoft ASP.NET WebAPI (http://www.asp.net/web-api)

Microsoft’s out-of-the-box solution for building HTTP-driven APIs. Superficially similar to ASP.NET MVC but I suspect there’s much more to it than that. I’ve built a couple of small standalone APIs in WebAPI but not used it for anything too substantial.

ServiceStack (https://servicestack.net/)

For a long while I was completely smitten with ServiceStack. Then it hit v4.0 and went from free-as-in-beer to expensive-as-in-$999-per-developer for any reasonable-sized project – there is a free usage tier, but it’s pretty restrictive. That said, it’s still a really powerful, flexible framework. Version 3 is still on NuGet, is still available under a BSD license, and there’s at least one active project based on a fork of the ServiceStack v3 codebase.  I like ServiceStack’s conventions and idioms; working with it taught me a lot about ReST; it has great support for things like SwaggerUI, and I suspect as I start implementing various API features ServiceStack is going to deliver additional value and capabilities which the other frameworks can’t match. Will it add enough value to justify $999 per developer? We’ll see :)

OpenRasta (http://openrasta.org/)

I’ve played with OpenRasta on-and-off over the years, though I’ve never used it on anything substantial, but I know the folks over at Huddle are using it in a big way and having great results with it, so I’m really curious to see how it stacks up against the others. (I should probably disclose a slight bias here in that Sebastien Lambla, the creator of OpenRasta, is a friend of mine; it was Seb who first got me thinking about ReST via London .NET User Group and prolonged conversations in the pub afterwards.)

NancyFX (http://nancyfx.org/)

This one is completely new to me – until last week, I’d never even looked at it. But so far, it looks really nice – minimalist, elegant and expressive, and I’m looking forward to seeing what it can do.

Other Candidates

It would be interesting to get some F# into the mix – mainly because I’ve never used F# and I’m curious. I’ve heard interesting things about WebSharper and Freya – and, of course, if anyone wants to add an F# implementation and send me a pull request, go for it!

The API

I’m using Apiary.IO to design the API itself – you can check it out at http://docs.restival.apiary.io/

The Code

The code is on GitHub - https://github.com/dylanbeattie/Restival.

If you want to run it, you’ll need to set up IIS applications for each of the four framework implementations – I use a hosts file hack to point restival.local at 127.0.0.1, and I’ve set up http://restival.local/api.webapi, http://restival.local/api.nancy, http://restival.local/api.servicestack and http://restival.local/api.openrasta

The test suite is NUnit, uses RestSharp to make real live HTTP requests, and all the actual test logic is in the abstract base class. There’s four concrete implementations, and the only difference is the URL of the API endpoint under test.

The Backlog

Features I want to implement include, but are probably not restricted to…

  • Pagination. What’s a good way to handle huge result sets without causing timeouts and performance problems?
  • Resource expansion. How do you request a customer, and all their orders, and the invoices linked to those orders, in a single API call?
  • API versioning – using all three different ways of doing it wrong
    • Version numbers in the URL (api.foo.com/v1/)
    • Version numbers in a custom HTTP header (X-Restival-Version: 1.0)
    • Content negotation based on MIME types (Accept: application/vnd.restival.v1.0+json)
  • OAuth2 and bearer token authentication. (You’ll like this one because I’m not using DotNetOpenAuth)
  • API documentation – probably by seeing how easily I can add Swagger support to each implementation

In every case, this is stuff I’ve already implemented in at least one project over the last couple of years, so it’s going to be interesting seeing how readily those implementations translate across to the other frameworks I’m using.

Sound like fun? You bet it does. Tune in and see how it unfolds. Or come to NDC Oslo in June or Progressive.NET in London in July, where you not only get to listen to me talk about ReST, you get several days of talks and workshops from some of the best speakers in the industry.

No comments: