Introduction
With help of this trick you can provide session state in you RESTful WebApi services.
Many of the devs like to use WCF REST, but on my opinion ASP.NET team provided us with mode powerful technology to develop more powerful REST services. Special thanks to them for that.
I have written this tip at frst time, and I hope people do not find it arrogant, it is certainly not meant to be .
Background
As far as you probably know, 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.
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.
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
.
Using the code
To enforce session in WebApi we need to use
IRequiresSessionState
markable attribute which is only need for notifying ASP
environment about providing session state on a specific module.
So as a result our self implemented
HttpControllerHandler
will be looked quite simple:
public class SessionableControllerHandler : HttpControllerHandler, IRequiresSessionState
{
public SessionableControllerHandler(RouteData routeData)
: base(routeData)
{}
}
So know we need only to plug our newly created SessionControllerHandler
to routing workflow. To do it we need to implement module
which will inherits IRouteHandler
interface and in GetHttpHandler
method just return new instance of session controller handler.
public class SessionStateRouteHandler : IRouteHandler
{
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
return new SessionableControllerHandler(requestContext.RouteData);
}
}
And last one.
We need in route registration add our route selection, for example:
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
).RouteHandler = new SessionStateRouteHandler();
vual ahhh
Our code is done.
To check the performance capacity of this approach lets do the next :
public class TestController : ApiController
{
public TestController()
{
}
public string GetFromSession()
{
if ((HttpContext.Current.Session["SomeData"] as string) == null)
HttpContext.Current.Session["SomeData"] = "Hello from session";
return (HttpContext.Current.Session["SomeData"] as string);
}
}
If you debug the code above few times, then you will see, that at first time of invoking GetFromsession
method in API controller, we will store some data in Session environment primarily,and all consequent execution of that method, will get this value from session storage and push it back to the wire.
Maybe my naming convention of classes sounds strange, but it's done only for evaluation purposes. Feel free with your own flavour of naming
History
No history is available, this is the first version.