views:

629

answers:

2

I have a web application the relies heavily on web services. Everything with the services is done asynchronously and with AddOnPreRequestHandlerExecuteAsync. Anyhow, most of my calls work just fine, but some are returning from their asynchronous service calls to find a null HttpContext.Current.Response/Request object in the endprerequest, which of course errors the instant I try to use either. Both objects (Response and Request are available/not null on beginprerequest of failing calls and work in the endprerequest of other calls).

Anyone run into similar, or have a guess as to what might be the problem?

Update: Seem to have found a solution, if I create a variable for the HttpApplication on Init(of the HttpModule this all occurs in) the HttpContext can be accessed from that variable.

Update: Passing either HttpApplication or HttpContext.Current on the begin function has the same issue. When passed as part of the "State" of the asynchronous call, they end up null in the end function, even though they are valid in the begin function.

Update: I've added some logging and found that the Asynchronous call I am making is returning correctly, the results are there, the callback function is invoked properly.

+1  A: 

I suspect I know the problem you're running into. The answer, almost certainly, is to replace usage of HttpWebRequest with WebClient, and to use the *Async methods of WebClient.

Here's the long explanation: there are two totally different Async programming models: the IAsyncResult Async Pattern and the Event-based Asynchronous Pattern. The IAsyncResult pattern uses BeginXXX and EndXXX methods, uses IAsyncResult instances, uses delegates for callbacks, and supports waiting for completion. The Event-based pattern uses XXXAsync methods to initiate async actions, uses XXXCompleted events instead of callbacks to handle completion, and (this is important to your case) transfers thread-specific context into every callback event handler.

In other words, if you put your callback code inside a XXXCompleted event handler (like WebClient.DownloadStringCompleted), then HttpContext.Current will be populated correctly.

If, however, you use a BeginXXX method (like HttpWebRequest.BeginGetResponse) and a delegate callback, your callback will be executed in the context of a thread that does not guarantee to have the right ASP.NET context attached.

Generally, .NET Framework library classes either use one async pattern or the other. Typically, the lower-level classes (e.g. HttpWebRequest) will use the IAsyncResult pattern, while the higher-level classes (e.g. WebClient) will use the event-based pattern. Some oddball classes (e.g. auto-generated .NET Remoting proxies) will support both patterns, but that's a rarity.

So if it's easy to do, I'd suggest moving to WebClient and event handlers instead of HttpWebRequest and callback delegates. This should solve your problem. If switching to WebClient is too hard, comment and I can probably suggest some more obscure alternatives.

Justin Grant
I'm not sure how easy this would be to implement in my case. I believe I am tied to the IAsyncResult pattern at least at the base level because that is the pattern that AddOnPreRequestHandlerExecuteAsync supports. And, since I have things working currently by simply saving the state in a variable, I'd prefer not to mess with it.
aepheus
A: 

Seem to have found a solution, if I create a variable for the HttpApplication on Init(of the HttpModule this all occurs in) the HttpContext can be accessed from that variable.

aepheus
Can you describe with details how did you solve the problem
omoto
In my HttpModule I have a variable of type HttpApplication. In the init() function call I set this variable to the HttpApplication that is passed to init. In the BeginPreRequestHandlerExecute and EndPreRequestHandlerExecute I refer to the current HttpContext using oApplication.Context, oApplication being the name of the HttpApplication variable in my HttpModule.
aepheus