HTTP Handlers and modules

Creating HTTP Handlers and HTTP Modules

May need to write code to handle actual HTTP request, e.g. image server, file processor, etc.

HTTP handler is endpoint on server that responds to resource requests, e.g. the ASP.NET page handler is called when ASPX page is requested. Write handlers to be called for resource with specific extension, e.g. ASP.NT tracing that accepts requests for .axd files

HTTP module gets called for every request or response routed to the application. Use to manage custom security, logging, etc.

HTTP Handlers

Create custom, synchronous handler by implementing IHttpHandler interface.

This interface exposes IsReusable property which if true will cause handler to be placed into pool to improve performance across requests.

The ProcessRequest method is called by ASP.NET to produce a response to the HTTP request.

The HTTP handler exists within ASP.NET so has access to application context - i.e. session state, application state and user identity.

public class ImageHandler : IHttpHandler
{
    public bool IsReusable { get { return false;} }

    public void ProcessRequest(HttpContext context)
    {
        context.Respone.ContentType = "image/jpeg";

        if (context.Request.RawUrl.Contains("jellyfish.jpg")
            context.Response.TransmitFile(context.Request.PhysicalApplicationPath + "/images/j,jpg");
        else
            context.Response.Write("File not found");
    }
}

After created register with IIS using its configuration tools.

First map custom extension to ASP.NET

Then map extension to the handler within the ASP.NET application.

ASP.NET also supports automatic registration of .ashx extension - in this case create page with .ashx extension and use the @WebHandler directive to point to custom HTTP handler code.

Can also register handler vis web.config. Method differs between IIS 6 and IIS 7.

In 6 use element for each extension to be handled:

<system.web>

    <httpHandlers>

        <add verb="*" path="*.jpg" type="ImageHandler" />

    <httpHandlers>

<system.web>

In 7 write similar code, but place inside different section:

<system.WebServer>

    <handlers>

        <add verb="*" path="*.jpg" type="ImageHandler" />

    <handlers>

<system.WebServer>

Forwarding requests to ASP.NET via Admin Interface

IIS only passes requests for specific file types to ASP.NET, for other types it passes the file from file system directly to browser.

As with web.config the process differs slightly between IIS 6 and 7.

To configure IIS 7:

  1. Open IIS Manager
  2. Navigate to your site (or default website)
  3. Double click Handler Mappings icon
  4. In Actions pane select Add Managed Handler
  5. In dialogue set Request Path to file name or extension to be mapped whilst Type allows the class name of HTTP handler to be chosen. Name field allows you to provide a descriptive name.

~~ Using The .ashx Extension

.ashx reserved for custom HTTP handlers - extension already registered with system.

For example generate class that implement IHttpHandler, perhaps basing it behaviour on query string contents.

Add a file to site with .ashx extension containing WebHandler directive to point to the class, e.g.

<%@ WebHandler Language="C#" Class="ImageHandlerQs" %>;

Can then call:

http://localhost:56560/lessons/MyImageHandler.ashx?jellyfish

Asynchronous Handlers and Pages

Allows request to execute on non-ASP.NET thread, allows ASP.NET to continue processing requests =>; responsive site.

Implementation can be tricky - use performance tools to verify performance under heavy load. Sometime overhead introduced by async programming can offset benefits.

  1. Creating Asynchronous HTTP Handler

ASP.NET will place handler on a separate thread.

The thread that would normally run synchronous HTTP handlers is then placed back into thread pool to handle additional user requests - reduces chance that limited set of ASP.NET threads will become exhausted.

Handler derives from IHttpAsyncHandler interface, override IsReusable and BeginProcessRequest.

public class AsyncImageHandler: IHttpAsyncHandler 
{
    public bool IsResuable { get { return false; } }

    public IAsyncResult BegineProcessRequest(HttpContext context, AsyncCallback cb, object extra)
    {
        ImageAsyncOp imageOp = new ImageAsyncOp(cb, context, extra);

        imageOp.StartAsync();
    }

    public void EndProcessRequest(IAsyncResult res) {};

    public void ProcessRequest(HttpContext context) {};
}

The class performing the operation derives from IAsyncResult. In this example the StartAsync method will queue a work item. This work item will cal the AsynCallback once processing is complete.

class ImageAsyncOp : IAsyncResult 
{
    AsyncCallback _cb;

    public ImageAsyncOp(AsyncCallback cb, HttpContext con, object state)
    {
        _callback = cb;

        ...
    }

    public void StartAsync()
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncOperation), null);
    }

    public void StartAsyncOperation(object workItemState)
    {
        ...

        _callback(this);
    }
}

Also provide callback method that gets called when asynchronous operation completes.

Any clean up that is required should be placed in EndPRocessRequest.

Asynchronous Webpage

No IIS registration required, just run the web page.

In @Page directive add Async=true:

<@Page Language="C#" Async="true" AutoEventWireup="true" %>;

In code behind file create methods called when async processing starts and ends:

protected IAsyncResult begin(object sender, EventArgs e, AsyncCallback cb, object extra)
{
    ImageAsyncOp io = new ImageAsyncOp(cb, this.Context, extra);
}

protected void End(IAsyncResult res) {};

Inside the Page_Load invoke the asynchronous opertion:

AddOnPreRenderCompleteAsync(new BeginEventHandler(gein), new EndEventHandler(end));

Custom HTTP module

Code executed every time page requested or response sent, similar to old ISAP filters except it is executed within CLR.

Create by deriving from IHttpModule interface.

Can write as assembly shared across multiple web apps, or just as a class in App_Code directory.

ASP.NETcreates instance of HttpApplication when you app starts. This classfinds any registered modules and creates instances of them.

Insidethe Init method of the HTTP module indicate which application eventsthe module handles.

public class LoggingModule : IHttpModule 
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += (new EventHandler(this.App_BeginReq));
    }

    public void App_BeginReq(Object source, EventArgs e)
    {
        ...
    }
}

Register HTTP modules via web.config:

<httpModules>
    <add name="LoggingModule" type="LoggingModule" />
<httpModules>

or

<modules>
    <add name="LoggingModule" type="LoggingModule" />;
<modules>

HTTP Modules and Global.asax

Global.asax can be used to register code for application events.

Do this by adding code to Application_BeginRequest, Application_LogRequest, etc.

This code runs just like HTTP module, but does not need registration.

Typically create HTTP Module to encapsulate complex code or share code across websites.

For simple needs the Global.asax is a better choice.

Download