Browse DevX
Sign up for e-mail newsletters from DevX


A Low-level Look at ASP.NET Architecture : Page 6

Many developers are familiar only with the high-level .NET frameworks like Web Forms and Web services that sit at the very top level of the ASP.NET hierarchy. This article discusses the lower-level aspects of ASP.NET and explains how requests move from Web Server to the ASP.NET runtime and then through the ASP.NET HTTP pipeline to process requests.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Modules are fairly low level and fire against every inbound request to the ASP.NET application. HTTP handlers are more focused and operate on a specific request mapping, usually a page extension that is mapped to the handler.

HTTP handler implementations are very basic in their requirements, but through access of the HttpContext object a lot of power is available. HTTP handlers are implemented through a very simple IHttpHandler interface (or its asynchronous cousin, IHttpAsyncHandler—see Sidebar 3), which consists of merely a single method—ProcessRequest()—and a single property, IsReusable. The key is ProcessRequest(), which gets passed an instance of the HttpContext object. This single method is responsible for handling a Web request start to finish.

Single, simple method? Must be too simple, right? Well, simple interface, but not simplistic in what's possible! Remember that Web Forms and Web services are both implemented as HTTP handlers, so there's a lot of power wrapped up in this seemingly simplistic interface. The key is the fact that by the time an HTTP handler is reached all of ASP.NET's internal objects are set up and configured to start processing of requests. The key is the HttpContext object, which provides all of the relevant request functionality to retrieve input and send output back to the Web server.

For an HTTP handler all action occurs through this single call to ProcessRequest(). This can be as simple as the code below:

public void ProcessRequest(HttpContext context) { context.Response.Write("Hello World"); }

Or it can be a full implementation such as the Web Forms page engine that can render complex forms from HTML templates. The point is that it's up to you to decide of what you want to do with this simple, but powerful interface!

Because the Context object is available to you, you get access to the Request, Response, Session and Cache objects, so you have all the key features of an ASP.NET request at your disposal to figure out what users submitted and return content you generate back to the client. Remember the Context object—it's your friend throughout the lifetime of an ASP.NET request!

The key operation of the handler should be to eventually write output into the Response object or more specifically the Response object's OutputStream. This output is what actually gets sent back to the client. Behind the scenes the ISAPIWorkerRequest manages sending the OutputStream back into the ISAPI ecb.WriteClient method that actually performs the IIS output generation.

Web Forms implements an HTTP handler with a much higher-level interface on top of this very basic framework, but eventually a WebForm's Render() method simply ends up using an HtmlTextWriter object to write its final output to the context.Response.OutputStream. So while it's very fancy, ultimately even a high level tool like a Web Form is just an abstraction on top of the Request and Response objects.

You might wonder at this point whether you need to deal with HTTP handlers at all. After all Web Forms provides an easily accessible HTTP handler implementation, so why bother with something a lot more low level and give up that flexibility?

Web Forms are great for generating complex HTML pages and business level logic that requires graphical layout tools and template backed pages. But the Web Forms engine performs a lot of tasks that are overhead intensive. If all you want to do is read a file from the system and return it back through code it's much more efficient to bypass the Web Forms Page framework and feed the file back directly. If you do things such as serve images from a database there's no need to go into the page framework—you don't need templates, and there surely is no Web UI that requires you to capture events off an image served.

There's no reason to set up a page object and session and hook up Page level events—all of that stuff requires execution of code that has nothing to do with your task at hand.

So handlers are more efficient. Handlers can also do things that aren't possible with Web Forms, such as processing requests without the need to have a physical file on disk, a concept known as a virtual URL. To do this make sure you turn off the "Check that file exists" checkbox in the Application Extension dialog shown in Figure 1.

Virtual URLs are common for content providers, such as dynamic image processing, XML servers, URL Redirectors providing vanity URLs, download managers, and the like, none of which would benefit from the Web Forms engine.

Have I Stooped Low Enough for You?
Phew—we've come full circle here through the processing cycle of requests. That's a lot of low level information and I haven't even gone into great detail about how HTTP modules and HTTP handlers work. It took some time to dig up this information and I hope this gives you some of the same satisfaction it gave me in understanding how ASP.NET works under the covers.

Before I'm done let's do the quick review of the event sequences I've discussed in this article from IIS to handler:

  • IIS gets the request
  • Looks up a script map extension and maps to aspnet_isapi.dll
  • Code hits the worker process (aspnet_wp.exe in IIS5 or w3wp.exe in IIS6)
  • .NET runtime is loaded
  • IsapiRuntime.ProcessRequest() called by non-managed code
  • IsapiWorkerRequest created once per request
  • HttpRuntime.ProcessRequest() called with Worker Request
  • HttpContext Object created by passing Worker Request as input
  • HttpApplication.GetApplicationInstance() called with Context to retrieve instance from pool
  • HttpApplication.Init() called to start pipeline event sequence and hook up modules and handlers
  • HttpApplicaton.ProcessRequest called to start processing
  • Pipeline events fire
  • Handlers are called and ProcessRequest method is fired
  • Control returns to pipeline and post-request events fire
It's a lot easier to remember how all of the pieces fit together with this simple list handy. I look at it from time to time to remember. So now, get back to work and do something non-abstract.

Although what I discuss here is based on ASP.NET 1.1, it looks like the underlying processes described here hasn't changed in ASP.NET 2.0.

Many thanks to Mike Volodarsky from Microsoft for reviewing this article and providing a few additional hints and Michele Leroux Bustamante for providing the basis for the ASP.NET Pipeline Request Flow slide.

Rick Strahl is the big Kahuna and janitor at West Wind Technologies in Maui, Hawaii. When he�s not out playing on waves and water, he likes to write code until the cows come home. Rick specializes in web and distributed applications with .NET and provides training and mentoring to clients and customers. He's also a C# MVP and ASP Insider, a frequent contributor to magazines and books, a frequent speaker at international developer conferences, and the co-publisher of CoDe Magazine. For more information please visit his Web site at www.west-wind.com.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date