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