Understanding ASP.NET Request Processing


When a request is received by the Web server, Internet Information Services (IIS) must first determine whether it is handling the request directly or the file extension is configured to be handled by an ISAPI extension DLL. Several types of files are configured for the aspnet_isapi.dll including ASP.NET pages (.aspx), XML Web Services (.asmx), and HTTP Handlers (.ashx). Figure 1-2 shows how a request for an .aspx page is processed.

click to expand
Figure 1-2: ASP.NET request processing

Let’s examine the process illustrated in Figure 1-2. The request for the .aspx page is made by the client Web browser. The Web server parses the request and hands it off to the aspnet_isapi.dll for processing. The ASP.NET run time then examines the request to determine which modules need to participate in the processing pipeline and which HTTP handler or HTTP handler factory will be given the request for processing.

The modules configured to participate in this request have an opportunity to modify the headers and output at several stages during processing, both before and after the handler or handler factory has processed the request.

ASP.NET pages are configured for an HTTP handler factory, which generates and compiles pages to handle the request. The page is executed, including a set of virtual page methods and events for which the developer might have provided custom code. The Web server returns the collected output back to the Web client.

IHttpHandler Interface

In the ASP.NET processing architecture, the request is ultimately handled by an object that implements either the IHttpHandler interface or the IHttpHandlerFactory interface. ASP.NET pages are handled by an IHttpHandlerFactory, which in turn instantiates and executes the page. The page itself implements IHttpHandler. To illustrate this, we implement our own IHttpHandler in Code Listing 1-1, SimpleHandler.cs. The SimpleHandler program implements the two elements of the IHttpHandler interface: the IsReusable property and the ProcessRequest method. By returning true for the IsReusable property, we indicate to the ASP.NET run time that a single instance of the handler can be used repeatedly. If we return false, a new instance must be created for every request.

Code Listing 1-1: SimpleHandler.cs

start example
 using System;
using System.Web;

namespace CodingStrategies {

public class SimpleHandler : IHttpHandler {

public bool IsReusable {
get {
return true;
}
}

public void ProcessRequest(HttpContext context) {
context.Response.Write("<html><head><title>SimpleHandler</title></head><body>");
context.Response.Write("<h2>The time is ");
context.Response.Write(DateTime.Now.ToString());
context.Response.Write(".</h2></body></html>");
}
}

}
end example

Tip

When implementing an IHttpHandler, you can get improved performance if ASP.NET is able to reuse a single instance of the handler. The object must be stateless to avoid introducing bugs related to multithreading.

The other interface member implemented in SimpleHandler.cs is the method that does the work. The ProcessRequest method is passed an HttpContext from which it can access the ASP.NET processing intrinsics such as HttpRequest and HttpResponse. In the SimpleHandler.cs sample in Code Listing 1-2, we render a simple HTML page that shows the current time on the server.

Code Listing 1-2 is a batch file for compiling the handler code into an assembly contained in a DLL. We specify that the type is a library and include a reference to System.Web.dll, where the handler interface and ASP.NET intrinsic classes are defined.

Code Listing 1-2: BuildSimpleHandler.bat

start example
 csc /target:library /reference:System.Web.dll  /out:CodingStrategies.dll SimpleHandler.cs 
end example

We also need to set up ASP.NET to use our handler instead of the regular IHttpHandlerFactory. Code Listing 1-3, HandlerWeb.config, is a web.config file that adds our handler to the configuration system. By setting the verb attribute to an asterisk, we indicate that all HTTP verbs are eligible. The path indicates which type of request should go to this handler. Here we specify the full page, time.axd. Requests for time.axd in this Web application will be routed to the SimpleHandler class. The path attribute also supports wildcards. We have chosen the .axd extension because it is already mapped in IIS to the ASP.NET ISAPI. You can create your own file extension for use in a handler, but you must add it to scriptmaps on the mappings tab of the Application Configuration dialog box in the Internet Information Services (IIS) Manager MMC snap-in. You can launch the snap-in from the command line by typing start inetmgr. Right- click the Web site or application icon and select Properties to get the Properties dialog box. When configuring a Web site, click the Configuration button on the Home Directory tab of the dialog box to reach the Application Configuration dialog box. To reach it when working with an application, click the Configuration button on the Virtual Directory tab. The type attribute in the web.config file specifies the assembly and class that implement the IHttpHandler interface.

Code Listing 1-3: HandlerWeb.config

start example
 <configuration>
<system.web>
<httpHandlers>
<add verb="*" path="time.axd"
type="CodingStrategies.SimpleHandler" />
</httpHandlers>
</system.web>
</configuration>
end example

IHttpModule Interface

When a request is handled by the ASP.NET run time, in addition to selecting a final IHttpHandler or IHttpHandler factory, a pipeline of IHttpModules is created based on the machine and application configuration files. The IHttpModule interface has just two methods, Dispose and Init. In the Init method, the module can add itself as a handler for events exposed by the page or by other modules. For example, ASP.NET uses modules for authentication and exposes an event that can be used by other modules or in the global.asax application code file. When the event occurs, code that has been registered as a handler for the event will be executed.

Part of the initial ASP.NET request processing is the creation of an HttpContext that is used throughout the rest of the pipeline to access information about the request, and to utilize the intrinsic objects like HttpRequest, HttpResponse, HttpCache, and Session, just as we do in the SimpleHandler.

Tip

The final implementation HttpHandler or HttpHandlerFactory might never be invoked if one of the HttpModules ends the request. This can minimize the load on the server when requests are serviced from the cache. When a request fails authentication or authorization checks, there is also no need to execute the handler.

The architecture of the ASP.NET request processing pipeline allows us to achieve the same type of functionality in HttpModules as is available with more complex ISAPI filters, and we can do it with managed code, leveraging the common language runtime. Code Listing 1-4, SimpleModule.cs, shows that an HttpModule can participate in and even take over a request.

Code Listing 1-4: SimpleModule.cs

start example
 using System;
using System.Web;

namespace CodingStrategies {

class SimpleModule : IHttpModule {

public void Init(HttpApplication application) {
application.BeginRequest += new
EventHandler(this.Application_BeginRequest);
}

public void Dispose() {
}

public void Application_BeginRequest(object source, EventArgs e) {
HttpApplication application = (HttpApplication)source;
application.Context.Response.Write("a module can end the request");
application.Context.Response.End();
}
}
}
end example

The HttpModule must be registered with the ASP.NET configuration, much like the IHttpHandler. Code Listing 1-5, ModuleWeb.config, is a web.config file with a single entry in the HttpModules section. This file does not replace the HttpModules configured in the machine.config but adds to that set.

Code Listing 1-5: ModuleWeb.config

start example
 <configuration>
<system.web>
<httpModules>
<add name="SimpleModule"
type="CodingStrategies.SimpleModule,
CodingStrategies" />
</httpModules>
</system.web>
</configuration>
end example

In the Init method, which is called on application startup by ASP.NET, we register our EventHandler for the BeginRequest event. That EventHandler is then called for each request. For more details about the events that occur during each request, see the section “Understanding the ASP.NET Page Life Cycle” later in this chapter.

Tip

The order in which HttpModules registered for an event are called is not guaranteed. Do not count on one HttpModule being called before another.

The object passed to the BeginRequest event is an HttpApplication object. From this object, we access the HttpResponse intrinsic, which we use to write output and then end the request.




Microsoft ASP. NET Coding Strategies with the Microsoft ASP. NET Team
Microsoft ASP.NET Coding Strategies with the Microsoft ASP.NET Team (Pro-Developer)
ISBN: 073561900X
EAN: 2147483647
Year: 2005
Pages: 144

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