Pages

Men

rh

7/01/2012

The Pipeline Event Model

The Pipeline Event Model
The ElapsedTimeModule in the previous example implements two event handlers, OnBeginRequest and OnEndRequest. These are just two of the events that an HttpApplication object fires in the course of processing an HTTP message exchange.  Note that the HTTP handler object that an instance of the HttpApplication class uses to ultimately process a request message is created between the ResolveRequestCache and AcquireRequestState events. The user session state, if any, is acquired during the AcquireRequestState event. Finally, note that the handler is invoked between the PreRequestHandlerExecute and PostRequestHandlerExecute events.

The HttpApplication class exposes all these events using multicast delegates so that multiple HTTP modules can register for each one. HTTP modules can register event handlers for as many of their HttpApplication objects' events as they like. However, modules should register for as few events as possible for efficiency's sake. Since an HttpApplication object and its modules will only be used to process one HTTP request at a time, individual HTTP module objects can store any per-request state they need across multiple events.

In some cases, an HTTP module may want to influence the flow of processing in the pipeline. For example, a module that implements a security scheme might want to abort normal message processing and redirect the client to a login URL when it detects that the HTTP request message does not include a cookie identifying the user. The HttpApplication object exposes the CompleteRequest method. If an HTTP module's event handler calls HttpApplication.CompleteRequest, normal pipeline processing is interrupted after the current event completes (including the processing of any other registered event handlers). A module that terminates the normal processing of a message is expected to generate an appropriate HTTP response message.

The code in Figure 9 provides an example of a module that uses CompleteRequest to abort the normal processing of a Web Service invocation. The SOAP specification's HTTP binding requires that an HTTP message carrying a SOAP message include a custom header called SOAPAction. The EnableWebServiceModule class's OnBeginRequest event handler examines the request message and if a SOAPAction header is present and the class's static enabled field is false, it stops further processing.

Figure 10 contains the source code for an HTTP handler called EnableWebServicesHandler that toggles the EnableWebServiceModule class's static enabled field whenever its ProcessRequest method is invoked.

Assuming that the source code for both the HTTP module and handler are compiled into a .NET assembly called Pipeline, the following entries in the Web.config file would be necessary for configuration: 

<configuration>
 <system.web>
  <httpModules>
   <add name="WebServicesEnabledModule"
    type="Pipeline.EnableWebServicesModule, Pipeline"
   />
  </httpModules>
  <httpHandlers>
   <add verb="*" path="toggle.switch"
    type="Pipeline.EnableWebServicesHandler, Pipeline"
  </httpHandlers>
 </system.web>
</configuration>
 
An IIS metabase entry associating the .switch extension with aspnet_isapi.dll would also have to be created and the Pipeline assembly would have to be deployed in the bin subdirectory of the Web server's virtual directory or in the GAC.

There is one other important point to mention about HTTP modules and the HttpApplication.CompleteRequest method. If a module aborts normal message handling during an event handler by calling CompleteRequest, the ASP.NET HTTP pipeline interrupts processing after that event completes. However, EndRequest and the events that follow are still fired. Thus, any modules that acquired valuable resources before processing was terminated have a chance to clean up those resources. For instance, if a module acquired a lock against shared state in its BeginRequest event handler, it can release the lock in its EndRequest event handler and be confident that the right thing will happen. The EndRequest event will fire even if some other module calls CompleteRequest and the HTTP message is never delivered to a handler.

No comments :

Post a Comment