HTTP Custom Handler Description

Description and samples
Table of Contents
Summary

Description of how to implement a full custom (i.e. not built-in) HTTP handler.

Description

An ASP.NET HTTP handler is the process executed in response to a request made to an ASP.NET Web application.

This type of process is referred to as the “endpoint“.

How it works

The HTTP Handler injects pre-processing logic based on:

  • The extension or path of the file name requested;
  • The HTTP verb sent on the request (i.e. method/action)

A new custom HTTP handler implemented in .NET can respond to any file name extension
or path that is not already mapped in IIS:

  1. The file extension or path must be mapped to the ASP.NET ISAPI extension DLL on IIS;
  2. The HTTP handler can be implemented in a separated DLL or as an application item in the ASP.NET App_Code directory;
  3. It must be registered on the web application. This configuration can be done on the “web.config” configuration file of each web application or for all aplications on the “machine.config” file.
When to use it

An advantage of using custom handlers over “.aspx” pages is that generic handlers are less complex since a page always involve firing several events which is always more expensive.

Customs handlers should be used instead of web forms when:

  • No data rendering is involved;
  • XML, JSON, text, images or other type of data is expected as response for the request

Syncrhronous and Asynchronous

An HTTP handler can be either synchronous or asynchronous:

A synchronous handler does not return until it finishes processing the HTTP request for which it is called.

An asynchronous handler runs a process independently of sending a response to the user.

The use of asynchronous handlers can prevent thread blocking and can improve performance because a limited number of threads
can execute at the same time:

The handler can instead continue processing without waiting for the external process to finish.

  • ASP.NET puts the thread that would ordinarily be used for the external process back into the thread pool until the handler receives a callback from the external process.

Factories

HTTP handler factories can be used to perform some preliminary tasks on the requested resource prior to passing it to appropriate HTTP handler.

On this scenario, different handlers can be instantiated based on run-time conditions like the file type or HTTP verb.

Operations
How to create a synchronous HTTP handler

To create a custom HTTP handler the following steps must be followed:

1) The HTTP handler class must implement the “System.Web.IHTTPHandler” interface, where:

1.1) The “ProcessRequest” method is responsible for processing individual HTTP requests. This method must include the code that produces the output for the handler that will be redirected as the response to the Cliente request.

1.2.) The “IsReusable” property specifies whether the IHttpHandlerFactory object (when used) can put the handler in a pool and reuse it to increase performance.

2) The custom HTTP handler must be registered on IIS; and

3) The file extension or path must be mapped to ASP.NET on IIS (only for IIS6.0 or previous versions)

How to do it
using System.Web;

public class syncHandler : IHttpHandler
{
	public syncHandler()
	{
	}

	public void ProcessRequest(HttpContext pContext)
	{
		HttpRequest Request = pContext.Request;
		HttpResponse Response = pContext.Response;
		Response.Write("<html>");

		Response.Write("<body>");
		Response.Write("<h1>Hello from a synchronous custom HTTP handler.</h1>");
		Response.Write("</body>");
		Response.Write("</html>");
	}

	public bool IsReusable
	{
		// To enable pooling, return true here.
		// This keeps the handler in memory.
		get { return false; }
	}
}
<configuration>

	<!-- Configuration for II6 and prior versions -->
	<system.web>

		<httpHandlers>
			<add verb="*" path="*/training/*.sync" type="syncHandler"/>
		</httpHandlers>

	</system.web>

	<!-- Configuration for II7 -->
	<system.webServer>

		<handlers>
			<add  verb="*" path="*/training/*.sync"
                  name="syncHandler"
                  type="handlers"
                  modules="IsapiModule" scriptProcessor="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"/>
		</handlers>

	</system.webServer>

</configuration>
How to create an asynchronous HTTP handler

To create a custom HTTP handler the following steps must be followed:

1) The HTTP handler class must implement the “System.Web.IHttpAsyncHandler” interface, where:

1.1) The “ProcessRequest” method is responsible for processing individual HTTP requests. This method must include the code that produces the output for the handler that will be redirected as the response to the Cliente request.

1.2.) The “IsReusable” property specifies whether the IHttpHandlerFactory object (when used) can put the handler in a pool and reuse it to increase performance.

2) The custom HTTP handler must be registered on IIS; and

3) The file extension or path must be mapped to ASP.NET on IIS (only for IIS6.0 or previous versions)

How to do it
using System;
using System.Web;
using System.Threading;

public class asyncHandler : IHttpAsyncHandler
{

    public bool IsReusable { get { return false; } }

    public asyncHandler() { }       

    public IAsyncResult BeginProcessRequest(HttpContext pContext, AsyncCallback pCallback, Object pData)
    {
        pContext.Response.Write("<p>Begin handler process (thread #" + Thread.CurrentThread.ManagedThreadId + ")</p>\r\n");

        // TODO: Build custom object with required data to be used on the task executed asyncronously (method "StartAsyncTask")
        // ...

        AsynchOperation asynch = new AsynchOperation(pCallback, pContext, pData);
        asynch.StartAsyncWork();

        return asynch;
    }

    public void EndProcessRequest(IAsyncResult pResult)
    {

    }

    public void ProcessRequest(HttpContext pContext)
    {
        throw new InvalidOperationException();
    }
}

class AsynchOperation : IAsyncResult
{
    private bool _completed;
    private Object _state;
    private AsyncCallback _callback;
    private HttpContext _context;

    bool IAsyncResult.IsCompleted { get { return _completed; } }
    WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } }
    Object IAsyncResult.AsyncState { get { return _state; } }
    bool IAsyncResult.CompletedSynchronously { get { return false; } }

    public AsynchOperation(AsyncCallback pCallback, HttpContext pContext, Object pState)
    {
        pContext.Response.Write("<p>Instantiated object AsynchOperation (thread #" + Thread.CurrentThread.ManagedThreadId + ")</p>\r\n");
        _callback = pCallback;
        _context = pContext;
        _state = pState;
        _completed = false;
    }

    public void StartAsyncWork()
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), _state);
    }

    private void StartAsyncTask(Object pWorkItemState)
    {
        // TODO: Implement call to external process here
        //...

        _context.Response.Write("<p>Executing external process (thread # " + Thread.CurrentThread.ManagedThreadId +")</p>\r\n");

        _completed = true;
        _callback(this);
    }
}
<configuration>

	<!-- Configuration for II6 and prior versions -->
	<system.web>

		<httpHandlers>
			<add verb="*" path="*/training/*.async" type="asyncHandler"/>
		</httpHandlers>

	</system.web>

	!-- Configuration for II7 -->
	<system.webServer>

		<handlers>
			<add verb="*" path="*/training/*.async"
                  name ="asyncHandler"
                  type="handlers"
                  modules="IsapiModule" scriptProcessor="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"/>
		</handlers>

	</system.webServer>

</configuration>
How to create a HTTP handler factory

To create a custom HTTP handler factory the following steps must be followed:

1) The interface “System.Web. IHttpHandlerFactory” interface must be implemented, where:

1.1) The “GetHandler” method is responsible for instantiate and return an HHTP handler object based on the request and HTTP verbs;

1.2.) The “ReleaseHandler” method is responsible to release used resources

2) The custom HTTP handler factory must be registered on IIS; and

3) The file extension or path must be mapped to ASP.NET on IIS (only for IIS6.0 or previous versions)

How to do it
using System;
using System.Web;

public class factoryHandler : IHttpHandlerFactory
{

	public IHttpHandler GetHandler(
						HttpContext pContext,
                        string pRequestType, String pUrl, String pPathTranslated)
	{
		IHttpHandler handlerToReturn;
		if ("get" == pContext.Request.RequestType.ToLower())
		{
			handlerToReturn = new syncHandler();
		}
		else if ("post" == pContext.Request.RequestType.ToLower())
		{
			handlerToReturn = new asyncHandler();
		}
		else
		{
			handlerToReturn = null;
		}

		return handlerToReturn;
	}

	public void ReleaseHandler(IHttpHandler handler)
	{
	}

	public bool IsReusable
	{
		get
		{
			return false;
		}
	}
}
<configuration>

	<!-- Configuration for II6 and prior versions -->
	<system.web>

		<httpHandlers>
			<add verb="GET,POST" path="*/training/*" type="factoryHandler"/>
		</httpHandlers>

	</system.web>

	<!-- Configuration for II7 -->
	<system.webServer>

		<handlers>
			<add verb="GET,POST" path="*/training/*"
				name ="factoryHandler"
				type="handlers"
				modules="IsapiModule" scriptProcessor="C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"/>
		</handlers>

	</system.webServer>

</configuration>