Static Access to Request-Specific Data

By on 11/3/2009

I wrote a post over on the nGenSoft Blog talking about how to gain Static Access to Request-Specific Data:
As we have all come to learn in the last decade plus of web development, web applications are inherently stateless.  Unlike their native client cousins, every request must be treated as if it was done in isolation from any other user action.  This can tend to complicate application level concerns.  More often than not people just end up polluting their application by mixing code that is related to servicing the http request, with their business logic.

We wanted a way to maintain application related plumbing such as database connections neatly maintained, without having to always worry about the stateless nature of http requests.  We noticed that ASP.NET has a really nice pattern that works really well in the HttpContext.Current property.  This is a static property that contains information about only the current request … at first I couldn’t figure out how this works because ASP.NET is by nature a multi-threaded environment.  How was it segregating the information, which is accessed statically, to each individual requests?

Update: repost of original text can now be found below

As we have all come to learn in the last decade plus of web development, web applications are inherently stateless. Unlike their native client cousins, every request must be treated as if it was done in isolation from any other user action. This can tend to complicate application level concerns. More often than not people just end up polluting their application by mixing code that is related to servicing the http request, with their business logic.

We wanted a way to maintain application related plumbing such as database connections neatly maintained, without having to always worry about the stateless nature of http requests. We noticed that ASP.NET has a really nice pattern that works really well in the HttpContext.Current property. This is a static property that contains information about only the current request ... at first I couldn't figure out how this works because ASP.NET is by nature a multi-threaded environment. How was it segregating the information, which is accessed statically, to each individual requests?

After doing some research online, I finally figured out a great way to maintain request level state across different components (ie. http module --> http handler --> mvc action filter --> etc.). I did a good bit of searching, but found it was succinctly put in a blog post by hanselman:

http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx

I started off by looking at (ie. Reflectoring) how the enigmatic HttpContext.Current works. Turns out there’s a lot of magic going on under the hood there with the web hosting framework and further .net remoting. In the end, looks like there are two simple ways to solve this problem:
  • [ThreadStatic] attribute lets you have an instance of your static *per* thread.
  • HttpContext.Current.Items, only usable in the context of asp.net obviously, but correctly manages your scope for the lifetime of the request.
As hanselman puts it:
Today's lesson learned:the [ThreadStatic] attribute is only useful when YOU control the ThreadPool (and the lifecycle of the threads).
So it seems that in order to solve the problem we need to adapt our strategy. If our app is running in a local client (ie. stateful), we can either use the threadstatic attribute, or nothing at all if we don't plan on doing complex multithreading. However, if we are executing our application's code in an asp.net app, we need to use HttpContext.Current.Items. Armed with this knowledge, we could have a small initialization step that lets you set up the strategy for how to manage session information. So in the app_start method of the global asax, we can do something like:
AppContext.SetEnvironment(new AppEnvironment());
Thus, in ASP.NET you have an implementation that can know how to provide the proper scoping for that hosting environment. AppContext is defined as:
public interface IAppEnvironment
{
    public AppContext Current { get; set; }
}
public class AppContext
{
    // instance data
    public IDatabase Database { get; set; }

// static lifecycl private static IAppEnvironment environment;

public static void SetEnvironment(IAppEnvironment env) { environment = env; }

public static AppContext Current { get { return environment.Current; } set { environment.Current = value; } } }
The instance data can be whatever you want … in the case of a data-driven app, it can maintain a request level database connection and whatever other information we need to refer to (which you can easily do by just saying “AppContext.Current.Database”). The static “Current” property that everyone would use simply defers to the environment implementation. Below are two implementations of the IAppEnvironment that you can use from ASP.NET and a custom one that you can use in a console app, or unit test.
public class WebEnvironment : IAppEnvironment
{
    public AppContext Current
    {
        get { return HttpContext.Current.Items["appcontext"] as AppContext; }
        set { HttpContext.Current.Items["appcontext"] = value; }
    }
}

public class CustomEnvironment : IAppEnvironment { [ThreadStatic] private static AppContext context;

public AppContext Current { get { return context; } set { context = value; } } }
The CustomEnvironment implementation above just uses the simple thread static attribute since it’s assuming that you will be managing the hosting environment (threading and all) … where in the WebEnvironment, you can defer to the httpcontext stuff since that is handled for you.

Techniques such as these let you focus on your application, while limiting the amount of time that you have to spend worrying complexities of adapting your application to run in a web application.

See more in the archives