Storing Contextual Data in Web and non-Web applications

In Asp.Net apps, we are used to storing data in the current context.  Objects that are specific to the currently executing Request, like a User object retrieved a database, or another object that you want to make globally available without requiring multiple database trips, can benefit from this.

But what about this situation in non-web applications?  Or what about situations like an assembly that needs to have this contextual caching logic coded into it, but needs to be used from both web and non-web applications?

Below is an example of a static property that stores a User object, which is retrieved from a database, in the current HttpContext.  If it is already available in Context, it simply returns it.

image

 

What will happen if this property is accessed from a non-Asp.Net application, such as a windows service?  HttpContext.Current will return null, and we will get an exception.

We could simply store a static field in this class and access that if HttpContext.Current is null. But if that application has more than one thread, such as a Windows Service that is hosting a WCF Service, the static field will be shared across all threads.

Right?

Right - Unless we add the [System.Threading.ThreadStaticAttribute] to it!

Below is the updated property that will work in both kinds of applications:

 

image

 

There you go - a property access to contextual variable that caches for the length of the current thread, and isolated to the current thread.

Awesome!

 EDIT: as was pointed out in the comments, I should have assigned the w variable to HttpContext.Items["MyClass.CurrentUser"]. Can you spot where it should go?  Thanks for the heads up, Dave!

Published Thursday, September 18, 2008 8:52 AM by joelvarty
Filed under: , ,

Comments

# re: Storing Contextual Data in Web and non-Web applications

Thursday, September 18, 2008 3:30 PM by Dave Transom

Thanks for the tip Joel. I've normally gone with the approach that if HttpContext.Current wasn't available, simply return a new instance and leave it to the app to cache. This solution is a bit more concise for encapsulation.

I think your example needs to set the HttpContext.Current.Items["MyClass.CurrentUser"] after retreiving it.

if(w == null)

{

  w = UserManagement.SelectUserDetails(CurrentUserID);

  HttpContext.Current.Items["MyClass.CurrentUser"] = w;

}

return w;