The HTTP Pipeline


At this point, we need to step back a little and look at the bigger picture. We know our handler has access to the HttpContext object for the request, but how? Why does web.config work as it does? Why did we map .wbsvc to aspnet_isapi.dll in IIS? Can we extend the mapping to apply to every Web application that IIS is hosting? The answers to these questions and many others surrounding extending the .NET Web Services framework lie in understanding how a HTTP request is processed by IIS and then ASP.NET.

From IIS to ASP.NET

Once an ASP.NET request has been allowed through your server’s firewall, typically via port 80 for HTTP or port 443 for HTTPS, your Web server picks it up and routes the request to the appropriate server-side pipeline for processing. In the case of IIS, it consults the Application Mappings list for the Web application the request is targeting and passes it to whichever version of aspnet_isapi.dll you’re using.

This DLL then forwards the request through a named pipe to the ASP.NET worker process, aspnet_wp.exe, which hosts a common language runtime (CLR) instance. It provides an application domain for each virtual application that IIS maintains. In this way, each application is isolated from the rest. The request is passed into the pipeline in the appropriate application domain and processed (as shown in Figure 5-5). Finally, IIS retrieves the response generated from the pipeline and sends it back as appropriate.

click to expand
Figure 5-5: How an ASP.NET request is passed to ASP.NET by IIS

You can configure as much of the operation of the worker process as needed. Every new application domain is created and operates under the settings laid out in the global machine.config file (and your application-specific web.config), which initializes the ASP.NET worker process. For example, each process is designed to handle requests indefinitely, but you can change the <processModel /> element in machine.config to specify a finite lifetime after which a process will be transparently replaced with a new instance of itself.

Important

IIS 6.0, which ships with Microsoft Windows Server 2003, brings some fairly large changes to this arrangement. Most notably, you can isolate separate applications in separate processes rather than having them grouped in a single process (as is the case in IIS 5.x). It also contains a kernel-mode HTTP listener, which can bypass aspnet_isapi.dll and send ASP.NET requests straight to the worker process.

You’ll find machine.config in WindowsDirectory\Microsoft.NET\Framework\Version\CONFIG. We’ll look more at .config files and the Web service–related entries within them shortly.

Inside the ASP.NET HTTP Pipeline

If we look more closely at the HTTP pipeline that the ASP.NET worker process maintains for every application domain, you can find our handlers and more. Programmatically, the pipeline is implemented by classes in the System.Web namespace (as shown in Figure 5-6) and configured using machine.config with any application-specific settings given in web.config.

click to expand
Figure 5-6: The ASP.NET HTTP pipeline. Read-only classes are drawn as rectangles.

A new request is marshaled from IIS to the beginning of the appropriate pipeline by an instance of HttpWorkerRequest.

At the top of the pipeline is HttpRuntime. It does two things:

  • It sends a request to the HttpApplicationFactory object to generate an HttpApplication object representing the Web application containing the requested file or Web service. The HttpApplicationFactory object generates the HttpApplication object by retrieving it from a pool that the HttpApplicationFactory object controls or by instantiating a new object if the pool is not yet full.

  • It creates an HttpContext object associated with the request. This wraps all the information pertinent to it (Response, Request, Server, and so forth) into a simple object model that is then available to the rest of the pipeline for state maintenance, reference, and reaction. The HttpContext object is passed automatically into the ProcessRequest method in your handler and can be retrieved by any other method using the static HttpContext.Current property.

The HttpRuntime, HttpApplicationFactory, and HttpContext classes implement the top half of the processing pipeline, which can’t be altered. While you’re writing handlers, the only evidence of the existence of these classes will be the HttpContext object passed into the ProcessRequest method. In contrast, the four objects in the bottom half of the pipeline provide you with hooks into the pipeline, giving you a good deal of control over the request and how it is processed:

  • HttpApplication provides application- and session-level state information to the modules and handlers that process the request. It also keeps track via machine.config and web.config of exactly which modules and which handler will do that processing, by looking in the <httpModules /> and <httpHandlers /> elements of those files, respectively. Finally, it exposes several events within the pipeline that can be hooked into by adding code to the global.asax file for the Web application.

  • Modules, which must implement IHttpModule, can view and alter the content of request and response messages as they flow through the pipeline. Indeed, any number of modules can work over a request before it reaches its intended handler. For example, two of the predefined modules in machine.config take care of the authentication and authorization of requests, respectively.

    Note

    Modules are the .NET equivalent of ISAPI filters. We’ll revisit them in Chapter 10. They are the key to extending the Web method programming layer of .NET’s Web service programming framework.

  • Handlers receive the request after it has been appropriately processed by any modules. The handler that receives a request is implemented by the class given in web.config (or machine.config, if it’s not application-specific).

  • A handler factory instantiates a handler if the handler doesn’t yet exist or is marked as not reusable. Alternatively, a handler can be instantiated directly. If it’s marked as reusable and an instance already exists, the handler will be reused. We’ll look at handler factories in more detail shortly.

Once a response to the request has been generated by the handler, it can be processed again by a module or two before it passes back up the pipeline, into IIS, and out to whatever client made the initial request.

Configuring the Pipeline for Your Application

Customizing the pipeline for your application boils down to working with the various .config files on your system. The machine.config file defines the default settings for the pipeline, and anything you override or add in the web.config file for your Web application must be based on the defaults. Be especially careful if you’re working with nested Web applications. Each application should have its own web.config file, and the overall settings for a child application will be the “sum total” of machine.config, all of its parents’ web.config files, and its own web.config file, as shown in Figure 5-7.

click to expand
Figure 5-7: A child application’s pipeline settings are the sum of the root’s settings, its parent’s settings, and its own.

If you open machine.config, you can find the settings for ASP.NET under <configuration>/<system.web>. The file contains brief documentation next to each setting to identify possible settings and what they do, but you can find clearer, more detailed explanations in the .NET SDK documentation at ms-help: //MS.NETFrameworkSDK/cpgenref/ html/gngrfaspnetconfigurationsection schema.htm.

The three sections we’re particularly interested in as Web service developers are <httpHandlers/>, <httpModules/>, and <webServices/>. The last of these presents the settings for ASP.NET Web service pages built using Web methods. They don’t help us at this lower level, but it’s worth noting that <webServices>/<protocols> lets you specify what types of requests these Web services will accept, and <webServices>/<WsdlHelpGenerator> lets you specify a new documentation page for them. You can find the default documentation page at WindowsDirectory\Microsoft.NET\Framework\Version\CONFIG\ DefaultWsdlHelpGenerator.aspx.

<httpHandlers/> and <httpModules/> can contain the following three subelements:

  • <add/>, which adds a module or a handler to the application, as in <add verb="*" path="*.ashx" type="System.Web.UI.SimpleHandlerFactory"/>

  • <remove />, which removes a module or a handler from the application that has already been defined globally or in a parent application, as in <remove verb="*" path="*.ashx" />

  • <clear />, which removes every handler or module from the application

Using the Predefined HTTP Handlers

Make sure you know exactly what <remove /> and <clear /> do. For instance, <remove verb="*" path="*.ashx" /> does not disallow requests to handler files—it removes any knowledge ASP.NET has of how to process them. Adding the above line to an application’s web.config and browsing to an .ashx file returns the entire source code in that particular file rather than a 404 File Not Found error or 403.1 Forbidden error, as was probably intended.

If you’re looking to return a standard error for a certain file or file extension, use the handlers that .NET has already defined. These aren’t particularly well documented, but Table 5-1 shows you which handler produces which error if you add the following line to your web.config and use the handler name in place of PredefinedHandlerName.

<add verb="*" path="your.path" type="System.Web.PredefinedHandlerName" />

Table 5-1: Errors Returned by Predefined .NET Handlers

Handler

Resulting Error Code and Message

Notes

HttpForbiddenHandler

HTTP 403: This type of page has been expressly forbidden.

N/A

HttpMethodNotAllowedHandler

HTTP 405: ‘GET’ is forbidden.

Change the verb in <add /> to restrict specific HTTP request methods.

HttpNotFoundHandler

HTTP 404: This resource cannot be found.

N/A

HttpNotImplementedHandler

HTTP 501: ‘GET’ *.extension is not implemented.

Change the verb in <add /> to restrict specific HTTP request methods.

At this point, we need to cut and run from everything but HTTP-SOAP requests. We might want to include online documentation for our service handlers, but the implementation of such pages is pretty trivial and, as you’ve seen, trivial to associate with a simple HTTP-GET request. However, with respect to actually conversing with the handler, HTTP-POST and HTTP-GET both have drawbacks:

  • Neither binding provides for the sending of header information specific to the conversation between client and service.

  • HTTP-GET doesn’t support the sending of complex types as name-value pairs in the query string.

  • You cannot ensure that the data contained in a message is correctly typed with either HTTP-GET or HTTP-POST.

  • Only the return parameter of the Web method can be returned using HTTP- GET or HTTP-POST. ASP.NET doesn’t support encoding in/out or out parameters within the message returned to the client as a result of an HTTP- GET or HTTP-POST request.

For debugging purposes, both bindings can be useful, but on a full, live server, you should lock down access to your services as much as possible. Prohibiting all except HTTP-SOAP requests is recommended for both Web method and handler-based services.




Programming Microsoft. NET XML Web Services
Programming MicrosoftВ® .NET XML Web Services (Pro-Developer)
ISBN: 0735619123
EAN: 2147483647
Year: 2005
Pages: 172

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net