Here it is. Shield your eyes while you look at Example 1 (just kidding—it's not a very big interface).
Example 1. The IHttpHandler interface
public interface IHttpHandler { void ProcessRequest(HttpContext ctx); bool IsReusable {get;} }
|
There's really not much to it, is there? The interface includes a method named ProcessRequest and a property named IsReusable. If the handler instance can be used multiple times, IsReusable should return true.
If the handler generally returns static content, it's probably
reusable. If the content is dynamic, it's probably not reusable. The
heart of the handler is the ProcessRequest method that includes a single parameter: the current HttpContext.
When a request finally arrives at the handler (through the ProcessRequest method), ProcessRequest can literally do anything to respond to the request. The Trace.axd
handler responds to a GET request by listing the requests being tracked
by the runtime. The forbidden handler responds by tossing a roadblock
in the processing pipeline so that the client can't see the forbidden
resource. A custom Web service might respond to the request by parsing
the XML payload, constructing a call stack, and making a call to an
internal method.
Implementing IHttpHandler is simple—at least from the architectural standpoint. The ProcessRequest method takes a single parameter—the current HttpContext. However, the code inside ProcessRequest
is free to do just about anything, possibly making the internal
processing quite complex! The following example illustrates taking over
the entire form-rendering process to display a list of choices in a
combo box, allowing the end client to select from the choices, and
finally rendering the chosen item.
Writing a custom handler
Create a new, empty Web project named CustomHandlers.
Add
a new class library subproject to the CustomHandlers solution (just as
you did when you created an HTTP module). Name the project CustomFormHandlerLib. The name of the class it generates for you is Class1. Rename the file CustomFormHandler.cs and the class CustomFormHandler.
The
library generated by Microsoft Visual Studio comes without any
knowledge of the ASP.NET framework and classes. Add a reference to the System.Web assembly.
To turn the CustomFormHandler class into an eligible handler, add the IHttpHandler interface to the inheritance list and implement ProcessRequest. Add a method named ManageForm that takes a parameter of type HttpContext. ManageForm should write out <html>, <body>, and <form> tags through Response.Write.
Write the question "Hello there. What's cool about .NET?" followed by a
line break. Next, write a <select> tag and set the name
attribute to "Feature." Then, write several .NET features surrounded by
<option> tags. This will produce a drop-down list box on the
client's browser. Write out an <input> tag. The tag's type attribute should be submit, its name attribute should be "Lookup," and its value attribute should be "Lookup." Next, look up the new value for the "Feature" selection tag in the HttpContext Request.Params collection. If the value is not null,
the end user selected something. Write the value provided by the
"Feature" selection tag. Finally, write out closing tags. That is,
</form>, </body>, and </html> tags.
Have the ProcessRequest method call the ManageForm method like so:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
public class CustomFormHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
ManageForm(ctx);
}
public void ManageForm(HttpContext context)
{
context.Response.Write("<html><body><form>");
context.Response.Write(
"<h2>Hello there. What's cool about .NET?</h2>");
context.Response.Write(
"<select name='Feature'>");
context.Response.Write(
"<option> Strong typing</option>");
context.Response.Write(
"<option> Managed code</option>");
context.Response.Write(
"<option> Language agnosticism</option>");
context.Response.Write(
"<option> Better security model</option>");
context.Response.Write(
"<option> Threading and async delegates</option>");
context.Response.Write(
"<option> XCOPY deployment</option>");
context.Response.Write(
"<option> Reasonable HTTP handling framework</option>");
context.Response.Write("</select>");
context.Response.Write("</br>");
context.Response.Write(
"<input type=submit name='Lookup' value='Lookup'></input>");
context.Response.Write("</br>");
if (context.Request.Params["Feature"] != null)
{
context.Response.Write("Hi, you picked: ");
context.Response.Write(
context.Request.Params["Feature"]);
context.Response.Write(
" as your favorite feature.</br>");
}
context.Response.Write("</form></body></html>");
}
public bool IsReusable {
get
{
return true;
}
}
}
The code in the ProcessRequest will render a form element and a select
element that render a form that can be submitted by the browser. When
the form is submitted back to the server, the parameter collection will
contain a Features
element. The code examines the parameter collection to see whether it
references a feature, and it displays the feature if it's been selected.
The
class library you just created deposits its output in the project
directory. For ASP.NET to use the page, the resulting executable needs
to live in the application directory's bin
subdirectory. You can do this by adding the CustomHandlerLib.dll as a
project reference to the Web site. Right-click the Web site project in
Solution Explorer and add a new project reference. Select the CustomFormHandlerLib project and click OK.
Now update web.config so that it uses the handler when clients request the CustomFormHandler resource. If you don't already have a web.config in the project, add one. Then, insert an httpHandlers section that points requests for the CustomFormHandler to the new CustomFormHandler class.
<configuration >
<system.web>
<httpHandlers>
<add path="*.cstm" verb="*"
type="CustomFormHandlerLib.CustomFormHandler, CustomFormHandlerLib"
validate="true" />
</httpHandlers>
</system.web>
</configuration>
Note:
If this site were running under IIS, you would need to tell IIS about the new file types to be handled by the CustomFormHandler.
If you decide to run this application under IIS (instead of the Visual
Studio Web server), you can configure IIS to run your handler by editing
config.sys directly, if you know the correct settings, or by doing the following:
Open IIS and navigate to the virtual directory for the site.
Open the Features View and locate the Handler Mappings icon, as shown in the following graphic.
Double-click the Handler Mappings icon to open the Handler Mappings page:
Right-click in the middle of the Handler Mappings page, and click Add Managed Handler.
Type
in an extension you'd like to have mapped to the custom handler, as
shown in the following graphic. Then, assign a handler. IIS will look at
all the handlers
available to your application (including the ones local to your
application). Select the handler from the drop-down list, give the
handler an alias, and you'll be able to surf to that file type to invoke
the handler.
Finally, add a blank text file named CustomHandler.cstm to your project. You can use the file with that extension to surf to the handler.
Surf to the customhandler.cstm resource, and ASP.NET will invoke the custom handler you just created, as shown in this graphic:
Of course, most of this
processing could be handled more easily by setting up a Web Form.
However, this example shows the flexibility of the ASP.NET handler
architecture. It should also give you more appreciation for the Web Form
and custom controls machinery in ASP.NET.