Adding Session support to ASP.NET Web API - StrathWeb

Strath

November 8th, 2012

Adding Session support to ASP.NET Web API

Because you might need it one day

First the disclaimer. Yes, there are a lot of problems with using session in your ASP.NET applications. Moreover, by default, HTTP (and by extension, REST) is stateless – and as a result each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP.

So if you are designing a proper API, if you are a REST purist, or if you are Darrel Miller, you definitely do not want to continue reading this article. But if not, and you find yourself in a scenario requiring session – perhaps you are using Web API to facilitate your JS or MVC application, and you want to sync the state of Web API with the state of MVC easily, or you simply want a quick and easy way to persist state on the server side – this article is for you.

More after the jump.

Adding session support with IRequiresSessionState

Let’s start by exploring how to extend Routes with Session state.

Web API routing, is operating on the same underlying ASP.NET RouteCollection, and therefore similar principles apply. ASP.NET has a concept of IRouteHandler which is a property on a System.Web.Routing.Route class and is responsible for processing HTTP requests for a route. By default, all Web API routes use HttpControllerRouteHandler which doesn’t do much, except handing over the HttpContexBase to HttpControllerHandler.

In order to provide session support, we will need to create 2 custom components:
IRouteHandler, to replace the default HttpControllerRouteHandler and to tell the ASP.NET pipeline to go to our custom HttpControllerHandler.
– customized HttpControllerHandler, which will mark the route as being session enabled and then go back to the Web API execution pipeline

So what now? That’s surprisingly easy.

In order to enforce session on the IHttpHandler, we simply implement the interface IRequiresSessionState (more about which you can read here). This is a so-called marker interface – so all you need to do is make the handler use it, and you don’t have to implement any methods.

This class does nothing more than introduce the marker interface, and hands the rest of the work to the default HttpControllerHandler which then continues with Web API execution pipeline.

By the way – this solution is inspired by the original proposal by Imran Baloch, who is doing great job for the ASP.NET community so make sure to follow his blog.

Plugging this in

So now we have session enabled, but how to plug this in in the first place?

Well, two steps:
1) create IRouteHandler that points to our new SessionControllerHandler
2) add it to the route when we register routes, so that a given route would use it

And now, in the route registration, we add our route handler:

Note, that I’m registering this against RouteTable.Routes directly, rather than GlobalConfiguration.Configuration.Routes. The reason for this is that the first collection is of type System.Web.Routing.Route (same as MVC) while the latter is of type System.Web.Http.Routing.IHttpRoute, and it does not allow you to set RouteHandler on it. Basically, this is us taking leverage on the fact that I mentioned in the beginning – that Web API routes and MVC routes are ultimately part of the same route collection.

Putting it to use

Now we are ready to go, and let’s create a simple Session wrapper to test our solution – you can use whatever you want, any session abstraction you like, this is purely for demonstration:

Now we can inject this into the controller, and use session in the GET action.

That’s it! Quick, easy and simple. We can test – on the 1st request, the object from session is obviously null.

Then, on the next one, it’s pulled from session:

Summary

There are probably many reasons why you DON’T want to use session.

At the same time, there are many scenarios when using session is the most viable solution and makes most business sense, especially as you don’t design pure API but rather use Web API to facilitate your MVC app – and you need i.e. a quick way to share artefacts between MVC and Web API.

While it’s not supported out of the box, with this approach you can quickly enable it without any problems.

Be Sociable, Share!

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1229

  • Pingback: Dew Drop – November 9, 2012 (#1,440) | Alvin Ashcraft's Morning Dew

  • Robert Slaney

    If you want to do this system wide you can also use the Application_PostAuthorizeRequest method in the global.asax.cs. Set System.Web.HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);

  • Pingback: Distributed Weekly 181 — Scott Banwart's Blog

  • Jason Meckley

    I tried implementing this, but it didn’t work. First I go the error, “duplicate route names”. both the mvc route collection and webapi routes where trying to register DefaultApi. I removed the WebApi route registration and then received the http response “404 resource does not exist”.

    I restored the original routes and used Rober Staney’s approach to requiring session for all requests. Everyhing is now working: MVC and WebApi routes are mapped and session is available in WebApi controllers.

  • Joseph Gabriel

    Thank you for being a voice of reason! I agree wholeheartedly that there are some cases where it doesn’t make sense to try force a web api to be fully stateless. I like how you phrased it, when you “use Web API to facilitate your MVC app”

  • Mahesh

    good one it works

  • concware

    I want to ask some help.

    I built in my project, everything is working, there is no exception or error. The only problem is the session object is always null and I can’t imagine where is the problem.

    Can you help me, please?

    Can you send me or attach a sample project?

    Thank you in advance!

  • mstechnewbie

    Where do you suggest we store the SessionControllerHandler and SessionRouteHanlder classes? Global.asax, WebApiConfig.cs, separate class files, or …?

    • http://www.strathweb.com/ Filip W

      yeah, i always store classes in separate files

  • Pingback: Getting SharePoint 2013 apps MVC Apps and ApiControllers to work | Bas Lijten

  • TimS

    Any ideas how can this be done with Web Api 2 / MVC 5?

    Appending this to the route config no longer works as there isn’t a RouteHandler property:
    .RouteHandler = new SessionRouteHandler();

  • Wajahat Mirza

    Session state works fine in MVC4 WebAPI by implementing above logic for HTTP Requests from a browser.

    But other HTTP Requests from another browser session state is never maintained and always returns null.

    Any suggestions…???