How to access session in web api controller in mvc4

I realize session and REST don’t exactly go hand in hand but it is not possible to access session state using the new Web API. HttpContext.Current.Session is always null. REST is stateless. If you use a session the processing will become stateful, subsequent requests will be able to use state (from a session).

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.

 public class SessionControllerHandler : HttpControllerHandler, IRequiresSessionState
{
    public SessionControllerHandler(RouteData routeData)
        : base(routeData)
    { }
}

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

public class SessionRouteHandler : IRouteHandler
{
    IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
    {
        return new SessionControllerHandler(requestContext.RouteData);
    }
}

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

public static void Register(HttpConfiguration config)
{
    RouteTable.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    ).RouteHandler = new SessionRouteHandler();
}

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

Complete Code

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            RouteTable.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            ).RouteHandler = new SessionRouteHandler();
        }
        
        public class SessionRouteHandler : IRouteHandler
        {
            IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
            {
                return new SessionControllerHandler(requestContext.RouteData);
            }
        }

        public class SessionControllerHandler : HttpControllerHandler, IRequiresSessionState
        {
            public SessionControllerHandler(RouteData routeData)
                : base(routeData)
            { }
        }
    }

Now we are ready, define session Session_Start in global.asax as below

protected void Session_Start()
{
    HttpContext.Current.Session.Add("Admin", "AdminUser");
}

and get this session in webapi as below

 public IEnumerable<Product1> GetAllProducts()
{
    var session = HttpContext.Current.Session;
    if (session != null)
    {
        string Admin = session["Admin"].ToString();
    }
    return products;
}

that’s it

Advertisements
This entry was posted in C#.NET, MVC and tagged , . Bookmark the permalink.

One Response to How to access session in web api controller in mvc4

  1. Veeeeery helpful. Thanks a lot

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s