ASP.NET has support for writing event handlers that can be notified at various times during the processing of an Http Request. One such event is the PreRequestHandlerExecute event. There is also asynchronous support for PreRequestHandlerExecute notifications that can be registered for using the AddOnPreRequestHandlerExecuteAsync method of the HttpApplication class. We are going to use the asynchronous PreRequestHandler option to provide an asynchronous execution mode for making our Web service calls.
The following are the steps for using the asynchronous PreRequestHandler execution after adding a Web reference:
- Creating a class implementing IAsyncResult and a custom proxy class.
- Creating a BeginEventHandler method, an EndEventHandler method, and an intermediate MyCallback.
- Calling the AddOnPreRequestHandlerExecuteAsync method.
- Using the response data.
You can find most materials about this approach in Matt Powell’s excellent article . The approach I present here is a slightly simplified version of Matt’s approach. I do not store a proxy and an IAsyncResult interface in a MyAsyncResult object. Instead of getting the response data of the Web service call in the EndEventHandler method, I get it in the MyCallback method.
Step 1. Creating a class implementing IAsyncResult and a custom proxy class
We provide an implementation of IAsyncResult which is used to store the request-specific state that we need to use during the processing of a request.
There are several changes made on the MyAsyncResult stubs for interface System.IAsyncResult, added by Visual Studio .NET by pressing TAB. The first is that we add two member variables: cb will be used to store the callback function passed by ASP.NET and be called when my asynchronous work has completed, and asyncState that holds the state for ASP.NET when it calls me. The second is that we implement the AsyncState property to support both reading and writing. The third is that we implement the CompletedSynchronously property. I’ll explain the implementation later.
Step 2. Creating a BeginEventHandler method, an EndEventHandler method, and an intermediate MyCallback
When a request comes in, the BeginEventHandler function will be called. This is when we will start our asynchronous Web service calls. The BeginEventHandler must return an IAsyncResult interface.
This method is being called for every HTTP request being handled by this virtual directory. Therefore, the first thing I do is check the actual path of the request and see if it is for the page that I am servicing or not.
My function is called with a couple interesting input parameters. The cb parameter is the callback function passed to me by ASP.NET. ASP.NET expects that when my asynchronous work has completed, the callback function it supplied me with will be called. That is ultimately how they will know when to call my EndEventHandler. The other interesting parameter is the extraData parameter that holds the state for ASP.NET when it calls me. I must return the state information when I invoke the callback function indicated by the cb parameter so I store it in the IAsyncResult class I created.
The MyCallback method is used to harvest the results of the asynchronous Web service call and relay the request to the EndEventHandler function.
Now is a good time to explain the implementation of the CompletedSynchronously property. ASP.NET will check the CompletedSynchronously property after BeginPreRequestHandlerExecute returns. If it is true, then ASP.NET calls EndPreRequestHandlerExecute. If it is false, then the method that checks the CompletedSynchronously property will return. It is up to the user to trigger cb.Invoke to go further. If cb.Invoke is called, then ASP.NET will check the CompletedSynchronously property again. If it is false, then ASP.NET will call EndPreRequestHandlerExecute and resume steps from a thread pool thread. If it is true, then the method that checks the CompletedSynchronously property will return. Now you understand why we need two “false” for the WebForm1.aspx page and one “true” for other pages.
Step 3. Calling the AddOnPreRequestHandlerExecuteAsync method
The call to the AddOnPreRequestHandlerExecuteAsync method of the HttpApplication class registers PreRequestHandlerExecute notifications.
Step 4. Using the response data
Using the response data is quite trivial.