Accessing ASP.NET Session from ServiceStack

This content is based heavily upon an answer I posted on StackOverflow. Oh, ok then, it’s almost an exact copy.

Recently, I’ve ripped WCF out of the heart of a project at work, and replaced it with ServiceStack. There were a couple of reasons for doing this.  Firstly, for the relatively simple API we wanted to expose, the configuration of endpoints and the like in `Web.config` for ServiceStack was overly complex, and also changed from client to client, depending on the base URL of their installation, and whether they ran our app over SSL or not.  It was a maintenance headache, and broke several releases because of mis-configuration.

Secondly, I wasn’t keen on the amount of attributes that had to be dotted around my code to make it work with WCF.  Also, classes in a WCF application often have dozens of methods, one for every service.  The cohesion of these methods if often low, so the classes really break the concept of single responsibility.  I wanted simper, more maintainable code!

ServiceStack has been a breath of fresh air. It prides itself on its simplicity, speed and friction-free development. Once configured in `Web.config`, the configuration is set in stone and doesn’t need to be tweaked.  I can add new web services to the code trivially, and ServiceStack uses reflection at application startup to determine the full set of web methods, and even exposes the metadata nicely at an API documentation page.

There was, however, one major problem.  Our application code relies quite heavily on the ASP.NET session, and in order to support this in a generic handler, the handler has to implement the marker interface `IRequiresSessionState`.

Unfortunately, ServiceStack didn’t do this in its generic handlers which are used to execute our web services. Instead, ServiceStack reimplements a light-weight, efficient Session object.  However, the use of ASP.NET’s own (inferior) session was so baked in to our application that replacing it wasn’t practical.  I had to find a solution.

To get around this limitation, I implemented two new classes, both of which use the decorator pattern to provide us with what we needed.

Firstly, a new IHttpHandler which requires session state. It wraps the IHttpHandler provided by ServiceStack, and passes calls through to it.

    public class SessionHandlerDecorator : IHttpHandler, IRequiresSessionState {
        private IHttpHandler Handler { get; set; }

        internal SessionHandlerDecorator(IHttpHandler handler) {
            this.Handler = handler;
        }

        public bool IsReusable {
            get { return Handler.IsReusable; }
        }

        public void ProcessRequest(HttpContext context) {
            Handler.ProcessRequest(context);
        }
    }

Next, a new `IHttpHandlerFactory` which delegates the responsibility for generating the `IHttpHandler` to ServiceStack, before wrapping the returned handler in our new `SessionHandlerDecorator`…

public class SessionHttpHandlerFactory : IHttpHandlerFactory {
    private readonly static ServiceStackHttpHandlerFactory factory = new ServiceStackHttpHandlerFactory();

    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) {
        var handler = factory.GetHandler(context, requestType, url, pathTranslated);
        return handler == null ? null : new SessionHandlerDecorator(handler);
    }

    public void ReleaseHandler(IHttpHandler handler) {
        factory.ReleaseHandler(handler);
    }
}

Then, it’s just a matter of changing the `type` attributes in the handlers in Web.config to `SessionHttpHandlerFactory` instead of `ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack`, and my web services then had the ASP.NET session available to them in `HttpContext.Current.Session`.

Recent Related Posts

2 thoughts on “Accessing ASP.NET Session from ServiceStack

  1. Hi,

    I have implemented the SessionHttpHandlerFactory and also replaced the tags from web config.

    But getting the forbidden response

    Forbidden
    Request.HttpMethod: GET
    Request.PathInfo:
    Request.QueryString: format=json
    Request.RawUrl: /Services/Resource1?format=json
    App.IsIntegratedPipeline: False
    App.WebHostPhysicalPath: D:\APP\AppName.Web
    App.WebHostRootFileNames:[list of pages]

    the AppHost Configuration is also done from Global.asax but still the url does not call service also f remove this Handler wrapper then this service url calls the service

Leave a Reply

Your email address will not be published. Required fields are marked *

*

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>