An HTTP Handler is a .NET class that executes whenever you make a request for a file at a certain path. Each type of resource that you can request from an ASP.NET application has a corresponding handler. For example, when you request an ASP.NET page, the Page class executes. The Page class is actually an HTTP Handler because it implements the IHttpHandler interface. Other examples of HTTP Handlers are the TRaceHandler class, which displays application-level trace information when you request the trace.axd page, and the ForbiddenHandler class, which displays an Access Forbidden message when you attempt to request source code files from the browser. You can implement your own HTTP handlers. For example, imagine that you want to store all your images in a database table. However, you want use normal HTML <img> tags to display images in your web pages. In that case, you can map any file that has a .gif or .jpeg extension to a custom image HTTP handler. The image HTTP handler can retrieve images from a database automatically whenever an image request is made. Or, imagine that you want to expose an RSS feed from your website. In that case, you can create a RSS HTTP Handler that displays a list of blog entries or articles hosted on your website. You can create an HTTP Handler in two ways. You can either create something called a Generic Handler or you can implement the IHttpHandler interface in a custom class. This section explores both methods of creating an HTTP Handler. Creating a Generic HandlerThe easiest way to create a new HTTP Handler is to create a Generic Handler. When you create a Generic Handler, you create a file that ends with the extension .ashx. Whenever you request the .ashx file, the Generic Handler executes. You can think of a Generic Handler as a very lightweight ASP.NET page. A Generic Handler is like an ASP.NET page that contains a single method that renders content to the browser. You can't add any controls declaratively to a Generic Handler. A Generic Handler also doesn't support events such as the Page Load or Page PreRender events. In this section, we create a Generic Handler that dynamically generates an image from a string of text. For example, if you pass the string Hello World! to the handler, the handler returns an image of the text Hello World!. The Generic Handler is contained in Listing 25.14. Listing 25.14. ImageTextHandler.ashx
The ImageTextHandler in Listing 25.14 includes one method and one property. The ProcessRequest() method is responsible for outputting any content that the handler renders to the browser. In Listing 25.14, the image text, font, and size are retrieved from query string fields. You specify the image that you want to return from the handler by making a request that looks like this: /ImageTextHandler.ashx?text=Hello&font=Arial&size=30 Next, a bitmap is created with the help of the classes from the System.Drawing namespace. The bitmap is actually created twice. The first one is used to measure the size of the bitmap required for generating an image that contains the text. Next, a new bitmap of the correct size is created, and the text is drawn on the bitmap. After the bitmap has been created, it is saved to the HttpResponse object's OutputStream so that it can be rendered to the browser. The handler in Listing 25.14 also includes an IsReusable property. The IsReusable property indicates whether the same handler can be reused over multiple requests. You can improve your application's performance by returning the value true. Because the handler isn't maintaining any state information, there is nothing wrong with releasing it back into the pool so that it can be used with a future request. The page in Listing 25.15 illustrates how you can use the ImageTextHandler.ashx file. This page contains three HTML <img> tags that pass different query strings to the handler (see Figure 25.4). Figure 25.4. Displaying text images with an HTTP Handler.Listing 25.15. ShowImageTextHandler.aspx
Implementing the IHttpHandler InterfaceThe big disadvantage of a Generic Handler is that you cannot map a Generic Handler to a particular page path. For example, you cannot execute a Generic Handler whenever someone requests a file with the extension .gif. If you need more control over when an HTTP Handler executes, then you can create a class that implements the IHttpHandler interface. For example, the class in Listing 25.16 represents an Image HTTP Handler. This handler retrieves an image from a database table and renders the image to the browser. Listing 25.16. App_Code\ImageHandler.vb
After you create a class that implements the IHttpHandler interface, you need to register the class in the web configuration file. The web configuration file in Listing 25.17 includes an httpHandlers section that associates the .gif, .jpeg, and .jpg extensions with the Image handler. Listing 25.17. Web.Config
When you register a handler, you specify the following four attributes:
The page in Listing 25.18 uses the ImageHandler to render its images. The page enables you to upload new images to a database named ImagesDB. The page also displays existing images (see Figure 25.5). Figure 25.5. Displaying images with the ImageHandler.Listing 25.18. ImageUpload.aspx
Registering Extensions with Internet Information ServerThe web server included with Visual Web Developer maps all requests to the ASP.NET Framework. For example, if you create an HTTP Handler that handles requests for .gif files, then you don't have to do anything special when using the handler with the Visual Web Developer web server. Internet Information Server, on the other hand, does not map all requests to the ASP.NET Framework. In particular, it does not map requests for .gif files to ASP.NET. If you want to use a special extension for a handler, then you must configure Internet Information Server to map that extension to the ASP.NET Framework. If you are serving your pages with Internet Information Server 6.0 (included with Windows Server 2003), then you can create something called a wildcard application mapping. A wildcard application mapping enables you to map all page requests to an application such as the ASP.NET Framework. Follow these steps to configure a wildcard mapping for ASP.NET:
After you complete these steps, all requests made for any type of file are handled by the ASP.NET Framework. If you make a request for a .gif image, then any handlers that you have registered in the web configuration file for the .gif extension will execute. Earlier versions of Internet Information Server, such as the version included with Microsoft Windows XP, do not support wildcard application mappings. You must map each file extension that you want to associate with the ASP.NET Framework one by one. Follow these steps to map the .gif extension to the ASP.NET Framework:
After you complete these steps, requests for .gif images are handled by the ASP.NET Framework. If you have registered an HTTP handler for the .gif extension in the web configuration file, then the HTTP Handler will execute whenever someone makes a request for a .gif file. Creating an Asynchronous HTTP HandlerWhen you create an HTTP Handler by creating either a Generic Handler or implementing the IHttpHandler interface, you are creating a synchronous handler. In this section, you learn how to create an asynchronous handler. The advantage of creating an asynchronous handler is scalability. The ASP.NET Framework maintains a limited pool of threads that are used to service requests. When the ASP.NET Framework receives a request for a file, it assigns a thread to handle the request. If the ASP.NET Framework runs out of threads, the request is queued until a thread becomes available. If too many threads are queued, then the framework rejects the page request with a 503Server Too Busy response code. If you execute an HTTP Handler asynchronously, then the current thread is released back into the thread pool so that it can be used to service another page request. While the asynchronous handler is executing, the ASP.NET framework can devote its attention to handling other requests. When the asynchronous handler completes its work, the framework reassigns a thread to the original request and the handler can render content to the browser. Note You can configure the ASP.NET thread pool with the httpRuntime element in the web configuration file. You can modify the appRequestQueueLimit, minFreeThreads, and minLocalRequestFreeThreads attributes to control how many requests the ASP.NET Framework queues before giving up and sending an error. You create an asynchronous HTTP handler by implementing the IHttpAsyncHandler interface. This interface derives from the IHttpHandler interface and adds two additional methods:
For example, the file in Listing 25.19 contains an asynchronous handler that grabs an RSS feed from the Microsoft MSDN website. Listing 25.19. App_Code\RSSHandler.vb
The handler in Listing 25.19 implements both the BeginProcessRequest() and EndProcessRequest() methods required by the IHttpAsyncHandler interface. The BeginProcessRequest() method uses the WebRequest class to request the page that contains the RSS headlines from the MSDN website. The WebRequest.BeginGetResponse() method is used to retrieve the remote page asynchronously. When the BeginGetResponse() method completes, the handler's EndProcessRequest() method is called. This method retrieves the page and renders the contents of the page to the browser. Before you can use the RSSHandler, you need to register it in your web configuration file. The web configuration file in Listing 25.20 includes an <httpHandlers> section that registers the RSSHandler and associates the handler with the .rss extension. Listing 25.20. Web.Config
After you register the RSSHandler, you can execute the handler by making a request for any file that ends with the extension .rss. If you have a news reader, such as SharpReader, then you can enter a path like the following in the reader's address bar: http://localhost:2026/YourApp/news.rss The page in Listing 25.21 contains a GridView and XmlDataSource control. The XmlDataSource control calls the RssHandler to retrieve the headlines that are displayed in the GridView control (see Figure 25.8). Figure 25.8. Retrieving an RSS feed asynchronously.Listing 25.21. ShowRSSHandler.aspx
|