ASP.NET

Writing a Custom Handler

Create a project named CustomHandlers. Make it an HTTP site that uses IIS. This will be important because IIS will need to direct requests for a specific file extension to use aspnet_isapi.dll.

  1. Add a new class library subproject to the CustomHandlers Web site (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.

  2. The library generated by Visual Studio comes without any knowledge of the ASP.NET classes. Add a reference to the System.Web assembly.

  3. To turn the CustomFormHandler class into an eligible handler, add the IHttpHandler interface to the inheritance list.

    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 within the ProcessRequest will render a <form> tag and a <selection> tag that renders a form that can be submitted on the browser. When the form is submitted back to the server, the parameters collection will have a Features element in it. The code examines the parameter collection to see if it references a feature, and displays the feature if it's been selected.

  4. The class library you just created deposits its output in the project directory. In order for ASP.NET to use the page, the resulting executable needs to live in the virtual directory's \bin subdirectory. Right-click on the CustomHandler solution (in the Solution Explorer) and add a bin directory to the project. Then highlight the CustomFormHandlerLib project, select the project's build properties, and the compiled output to point to the bin directory. While you're in the configuration page, make sure the name of the target assembly is CustomFormHandlerLib.

  5. 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
    xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
       <appSettings/>
       <connectionStrings/>
    <system.web>
        <httpHandlers>
           <add path="customformhandler" verb="*"
           type="CustomFormHandlerLib, CustomFormHandler" validate="True" />
        </httpHandlers>
    </system.web>
    </configuration>
    
  6. You need to tell IIS about the new file types to be handled by the CustomFormHandler. Open IIS and drill down to the CustomHandler virtual directory. Right-click on the directory and select Properties. Then click the Configuration button to show the file types and their mappings.

    Graphic
  7. Click the Add button and create a mapping between files with the extension *.cstm and aspnet_isapi.dll. You can use the Browse button to search for the aspnet_isapi.dll assembly in the Windows directory on your machine.

    Graphic
  8. Finally, create a blank file named CustomHandler.cstm in the IIS virtual directory. The file with that extension needs to be there to work.

  9. Surf to the customhandler.cstm file and ASP.NET will invoke the handler.

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 within ASP.NET.

The CustomFormHandler Using VB

From the runtime's point of view, it doesn't matter how the handler was written-it just needs to fully implement the IHttpHandler interface. Listing 18-3 illustrates the same handler written in VB.NET.

Listing 18-3
Imports System.Web

Public Class CustomFormHandlerVB : Implements System.Web.IHttpHandler
    Public Sub ManageForm(ByVal context As HttpContext)

        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")) <> Nothing Then
            context.Response.Write("Hi, you picked: ")
            context.Response.Write(context.Request.Params("Feature"))
            context.Response.Write(" as your favorite feature.</br>")
        End If
        context.Response.Write("</form></body></html>")
    End Sub

    Public ReadOnly Property IsReusable()_
      As Boolean Implements System.Web.IHttpHandler.IsReusable
        Get
            Return True
        End Get
    End Property

    Public Sub ProcessRequest_
       (ByVal context As System.Web.HttpContext) Implements
System.Web.IHttpHandler.ProcessRequest
       ManageForm(context)
    End Sub
End Class

The example accompanying this tutorial includes the previous handler named CustomFormHandlerVB in an assembly named CustomFormHandlerLibVB. Listing 18-4 shows how to refer to the second handler.

Listing 18-4
<httpHandlers>
   <add path="customhandler.cstm" verb="*"
      type="CustomFormHandler, CustomFormHandlerLib" validate="True"/>
   <add path="customhandlerVB.cstm" verb="*"
      type="CustomFormHandlerVB, CustomFormHandlerLibVB" validate="True"/>
</httpHandlers>