Tuesday, 23 April 2013

Extending ServiceStack

I’ve been using ServiceStack on a couple of projects recently and I have to say I’m well impressed, it’s a superbly written set of assemblies, really well thought out, extremely fast and extensible too.

One of the things I’ve been struggling with however is how to inject an implementation of an interface into the pipeline before everything else. The API I’m exposing requires a couple of Http headers to be present, and not only do these need to be verified as present, but I want to use them to initialise one of the services (we’ll call it IMerchantTokenService) that other parts of the application need.

The general process I’d like to go through is as follows…

  • When an HTTP Request comes in, check for the headers
    • If they exist, create an implementation of IMerchantTokenService that contains these headers and stuff it into the IOC container. If not, throw an exception.
    • As IMerchantTokenService is now registered in the IOC container, when I resolve any other services that have this as a requirement it will be injected into all of these other services too.

Like most things, until you “get” the API you’re left wondering how to implement a feature, and once you know the API it’s second nature. This was one of those days.

After some fruitless tinkering I took a step back and thought – my headers requirement sounds a lot like an HTTP session (even though it’s used for something different). So I went and had a look at how ServiceStack deals with sessions and, sure enough, that was also the place where I could plug in my stuff. It’s easy when you know how.

The feature I was searching for is called a “Plugin”. Simply put, a plugin allows you to attach some extra processing to the request pipeline in ServiceStack, and you can get in before your service is instantiated and therefore affect which service(s) are available to import into your dependencies.

Writing a plugin

Creating a plugin is trivially easy – create a class that derives from IPlugin, override the Register method and bingo, you’re in business…

Code Snippet
/// <summary>
/// This class provides a plug-in that's called prior to any services being
/// executed. It verifies that the required header values are in place,
/// and registers a service so that other objects can access these
/// values later in the cycle
/// </summary>
public class MerchantTokenFeature : IPlugin
    /// <summary>
    /// Add a callback so that we get called when a request comes in
    /// </summary>
    /// <param name="appHost">The hosting provider</param>
    public void Register(IAppHost appHost)
        if (null == appHost)
            throw new ArgumentNullException("appHost");

        _appHost = appHost;

    /// <summary>
    /// Process the request headers
    /// </summary>
    /// <param name="request">The Http request</param>
    /// <param name="response">The Http response</param>
    private void PreFilter(IHttpRequest request, IHttpResponse response)
        string apiKey = request.Headers[Headers.APIKey];
        string merchantIdentifier = request.Headers[Headers.MerchantIdentifier];

        if ((null == apiKey) || (null == merchantIdentifier))
            throw HttpError.Unauthorized(string.Format("You must send the {0} and {1} headers", Headers.APIKey, Headers.MerchantIdentifier));

        _appHost.Register<IMerchantTokenService>(new MerchantTokenService(apiKey, merchantIdentifier));

    private IAppHost _appHost;

This plug-in hooks an additional entry into the PreRequestFilters collection, and so when a request comes in my PreFilter method is called and I can check the Http headers and then manually construct the additional service.

Registering your PlugIn

The only other requirement is to register the plug-in. In the Configure method of your AppHostBase derived class just add the plugin…

Code Snippet
public override void Configure(Funq.Container container)
    SetConfig(new EndpointHostConfig { ServiceStackHandlerFactoryPath = "api" });
    Plugins.Add(new MerchantTokenFeature());

That’s it – up and working. I can now import IMerchantTokenService wherever I need, and know that this dependency will be available by the time my service gets instantiated and it starts looking for it’s own dependencies.


Richard Majece said...

I have a huge amount of applications in my phone so I was scared when I lost it. https://cellspyapps.org/track-phone-number/ helped me to track my phone number and find it)

Veronica Segura said...

I love to read your blog post. You are really doing good to attract the readers. Actually I don’t make comments on every post I visit. Just wish to say your article is as surprising. Must say it is such a nice post. I used to be checking continuously this blog and I’m inspired! Extremely helpful info particularly the final phase :) I care for such information a lot. I was seeking this certain info for a very long time. Thanks and best of luck for your future work. Feel free to visit my site: Write my Essay for any writing related help.

jacklinemelda said...

Our company is the best online solution in offering college term papers for sale since we hire professional writers who have years of experience in buy custom essay papers services.

meldaresearch said...

We are the best writing company providing Buy College Papers Online to students across the globe.We are a UK based company and have been operational since 2005 where we have assisted thousands of students in attaining high marks in Custom College Essay Writing Service.