Creating a basic catalogue endpoint with ServiceStack

Overview

Servicestack is a comprehensive web framework for .NET that allows you to quickly and easily set up a REST web service with very little effort. We already use OpenRasta to achieve this same goal within our stack, so I thought it would be interesting to compare the two and see how quickly I could get something up and running.

The thing that most interested me initially about ServiceStack was the fact that it claims out of the box support for Memcached, something we already use extensively to cache DTOs, and Redis; the ubiquitous NoSql namevaluecollection store.

Getting cracking

I set myself the task of creating a basic endpoint for accessing 7digital artist, release and track details. Whilst taking advantage of ServiceStack’s ability to create a listener from a console window so I didn’t have to waste time attempting to set it up via IIS:

class Program {
      static void Main(string[] args) {

      var appHost = new AppHost();
      appHost.Init();
      appHost.Start("http://localhost:2211/");
      Console.Read();
   }
}

As you can see this couldn’t be simpler. Whilst the thread is running, it will listen at localhost on port 2211 for incoming requests.

AppHost

Every ServiceStack implementation starts with the concept of an AppHost, which is a catch all class that exposes the initial setup of your service. For a console app based HttpListener setup It relies on you overriding the AppHostHttpListenerBase.Configure() method, which offers up a Container for access to the built in IOC. Funq is the weapon of choice in Service Stack.

It seems a shame that Service Stack doesn’t abstract away the responsibility of the IOC, allowing the developer the case to write their own IOC implementation as you can with OpenRasta, but the emphasis with ServiceStack is on speed (both of performance and setup) and Funq is perfectly adequate.

Routes

The AppHost is where it is suggested that you set up the concept of Routes, which like with the ConfigurationSource in OpenRasta, you set up your Resource – UriTemplate relationship:

Routes
    .Add<Artist>("/artist/details")
    .Add<Artist>("/artist/details/{Id}")
    .Add<Release>("/release/details")
    .Add<Release>("/release/details/{ReleaseId}");

As with OpenRasta, the resource is represented by a simple DTO. In exactly the same way (via the KeyedValueBinder attribute in OR) your DTO represents the incoming request parameters, or POST request representation of your resource.

Services

The actual service itself (the equivalent of the Handler in OR) is where the request gets processed. There are a couple of ways you can accomplish this, but I opted for the documented method of deriving from the RestServiceBase<TResource> class. From within here you can the override a set of “On” methods which ServiceStack routes the call through to depending on the verb used, for example:

public override object OnGet(Artist request) {
    // Service logic here
}

Those familiar with OpenRasta will recognise a similar concept in setting up of Handlers, but with a few subtle but important differences. OpenRasta successfully decouples the concept of a handler from your implementation by allowing you to tie it to a resource elsewhere, which from a clean code perspective I prefer.

OpenRasta also more importantly does not assume that you will be implementing all http verbs within a handler, and returns a valid 405 Method Not Allowed if you have not implemented that method for a service.

IOC implementation

ServiceStack’s default Funq works very well and you can opt for both constructor injection or property injection. Ctor injection is our (and should also be your) preferred way of achieving this, and Funq handled this perfectly.As mentioned earlier, you set up your container within the AppHost. You can then use the familiar Register<TInterface>(ConcreteInstance) to set up your dependencies..

MediaTypes / Features

ServiceStack’s great selling point is the ability to set up a “vertical slice” of a site incredibly quickly, and this it does without fail. Once I had my resource DTOs, service and AppHost set up I was able to access it immediately. It also supports many different media types out of the box, which can be turned off and on within the AppHost like so:

SetConfig(
   new EndpointHostConfig
   {
      EnableFeatures = Feature.All.Remove(Feature.All)
      .Add(Feature.Xml | Feature.Json | Feature.Html),
   }
);

Caching and ReDis

ServiceStack is true to its word that it supports a caching layer out of the box, and it is really easy to set up. It comes with its own MemoryCacheClient which works well as a basic .NET IDictionary implementation of a cache. It supports TTLs but not sure about LRU (least recently used) or other caching strategies.

Each Cache class implements the ICacheClient class, and you just set up the dependancy in the AppHost in the normal way. You can then inject it into your caching service as normal. I implemented it in my ArtistDetails

ReDis works in exactly the same way, and it does just work. I was very impressed with it’s implementation.

It would have been nice to test its Memcached setup, but that didn’t come with the latest release, it’s only available within the latest cut from github. I downloaded it, but due to some initial setup issues ran out f time before I could play with it. It’s essentially an adapter around the Enyim library which we already use for our Memcached setup.

Pipeline vs ResponseFilters

OpenRasta allows you the ability to “hook into” various stages of its pipeline process outlined here. I wanted to see if ServiceStack did the same and I got very excited when I saw the concept of ResponseFilters, which again are set up in the AppHost. Sadly I ran out of time on this, I wanted to try and implement a “catch all” way of dealing with my http response codes issue as mentioned above, but this could be something I investigate further at a later date.

HttpStatusCodes

My biggest issue with ServiceStack after poking around a bit revolved around status responses. If, within a service, you have not overridden a method for a specific http verb then you do not get a nice instant 405 Method Not Allowed response. You instead get a 500 Internal Server Error with the available mime-type representation of the error object and stack trace.

In an attempt to rectify this, I ended up creating an interim ErrorHandlingRestServiceBase<TResource> abstract class as follows:

public abstract class ErrorHandlingRestServiceBase<T> : RestServiceBase<T>
{
     protected override object HandleException(T request, Exception ex) {
         if (ex is NotImplementedException)
             return new HttpResult(ex)
                    { StatusCode = HttpStatusCode.MethodNotAllowed };

         return base.HandleException(request, ex);
     }
 }

The service then derives from this. Not the most elegant solution, but the only way I could see you it could be done. Having to implement functionality through inheritance rather than loosely coupled hooks can lead to complexity over time.

CustomSerialization

Another thing I didn’t get a chance to look at in more detail was customising your final mime-type related representation of your resource on the way back to the client. OpenRasta handles this excellently through the concept of a Codec, which is hooked up as a representation of a Resource with the ResourceSpace.Has syntax. This helps to leave the implementation of the request decoupled from the representation of the resource.

ServiceStack doesn’t seem to have an equivalent of this concept. In an attempt to ease you into an out-of-the-box implementation, it takes care of this all for you.

Summary

In my opinion, ServiceStack does deliver on its promises, it’s intuitive, user friendly and quick to set up. I’m sure if I’d had as much time with it as I have had with OpenRasta, I’d have found out ways around the issues outlined above. Currently I don’t see anything that would prompt me to think about using it instead, but as a simple framework to quickly get an application up and running it’s definitely a winner.

The project is available here

Links

About Greg Sochanik

a .net software developer at 7digital, on the silicon roundabout. Living in angel with his lovely wife, little baby boy and mischievous cocker spaniel. Follow me on twitter @gregsochanik
This entry was posted in OpenRasta, REST, Software Development and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>