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.

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:

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

publicinterfaceIDataPersistance<T>

{

TObjectValue{get;set;}

}

publicclassSessionDataPersistance<T>:IDataPersistance<T>

whereT:class

{

privatestaticstringkey=typeof(T).FullName.ToString();

publicTObjectValue

{

get

{

returnHttpContext.Current.Session[key]asT;

}

set

{

HttpContext.Current.Session[key]=value;

}

}

}

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.

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);

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 …?