While preparing for a talk at Win-Dev this week titled Security Context in Multithreaded Applications, I investigated how much security-related information (CAS demands/denies/permits, call context, thread principal, etc) was propagated from one thread to another using various techniques (ThreadPool.QueueUserWorkItem, async delegates, dedicated threads, etc) on the 1.1 and 2.0 runtimes. I also explored the new types in Whidbey that let a programmer control context propagation manually. For the most part, this is great stuff - solving a problem I've long had when trying to implement a custom thread pool on pre-Whidbey CLRs that not only dealt with the mechanics of providing thread pool services, but also tried to allow threads in the pool to temporarily imitate everything about the security-related context of the thread that placed each work request to the queue.
As it turns out, however, if you build async web pages in Whidbey, then you need to be careful about using libraries that depend on dereferencing HttpContext.Current to get their hands on the current HttpContext object. At least in the Whidbey beta 1 build, it's null, which is a bummer.
It's not catastrophically bad - just really annoying - because most of the time, you're going to be getting a callback from some async technique (delegate, web service call, etc) to an instance method on your Page object. And the Page instance is still going to be setup just fine. So if you want to get your hands on the current HttpContext, you can still use this.Context from within an instance method on your page. But if your page is using any library functions that do stuff like this:
class Widget {
public static void DoSomething() {
HttpContext ctx = HttpContext.Current;
// use ctx...
}
}
then they won't work if called asynchronously. You'll need to contrive some means of passing your page's context down to those methods, either explicitly:
void SomePageMethodInvokedAsynchronously() {
Widget.DoSomething(this.Context);
}
...
class Widget {
public static void DoSomething( HttpContext ctx ) {
// use ctx...
}
}
or implicitly:
void SomePageMethodInvokedAsynchronously() {
CallContext.SetData(“httpContext“, Context);
Widget.DoSomething();
}
...
class Widget {
public static void DoSomething() {
HttpContext ctx = (HttpContext)CallContext.GetData(“httpContext“);
}
}
Everything else (principal, CAS perms, etc) propagates fine - just not HttpContext.Current. So beware.
One last note - I tested this using a simple async delegate, which propagates “everything”. If another technique is used to get asynchrony (like async web services) then results could be different. Using a proper async web service is a test for another day...
Posted
Oct 27 2004, 12:07 PM
by
mike-woodring