Friday, October 21, 2011

ASP.net 4.0 HttpHandler Routing Support

I'm a big fan of ASP.net Routing and I use it a lot on my ASP.net Webforms applications.

If you're just getting started with Routing on ASP.net Webforms I recommend reading this post from Scott Guthrie.

Ok now, back to the subject, one thing about Routing is that it doesn't support routes that point to HttpHandlers (common .ASHX files).

The code bellow comes just to overcome this limitation by adding a new method (and one overload) to the RoutesCollection object that will let you map a route to an *.ashx url or directly to the handler object.

Edit (2011/11/03): I just updated this due some problems when reusing the same handler for different requests. Now each request gets its own handler like it should.

The Code

namespace System.Web.Routing
{
 public class HttpHandlerRoute<T> : IRouteHandler where T: IHttpHandler
 {
  private String _virtualPath = null;

  public HttpHandlerRoute(String virtualPath)
  {
   _virtualPath = virtualPath;
  }

  public HttpHandlerRoute() { }

  public IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
   return Activator.CreateInstance<T>();
  }
 }

 public class HttpHandlerRoute : IRouteHandler
 {
  private String _virtualPath = null;

  public HttpHandlerRoute(String virtualPath)
  {
   _virtualPath = virtualPath;
  }

  public IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
   if (!string.IsNullOrEmpty(_virtualPath))
   {
    return (IHttpHandler)System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(IHttpHandler));
   }
   else
   {
    throw new InvalidOperationException("HttpHandlerRoute threw an error because the virtual path to the HttpHandler is null or empty.");
   }
  }
 }

 public static class RoutingExtension
 {
  public static void MapHttpHandlerRoute(this RouteCollection routes, string routeName, string routeUrl, string physicalFile, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null)
  {
   var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute(physicalFile));
   routes.Add(routeName, route);
  }

  public static void MapHttpHandlerRoute<T>(this RouteCollection routes, string routeName, string routeUrl, RouteValueDictionary defaults = null, RouteValueDictionary constraints = null) where T : IHttpHandler
  {
   var route = new Route(routeUrl, defaults, constraints, new HttpHandlerRoute<T>());
   routes.Add(routeName, route);
  }
 }
}

How to use it

// using the handler url
routes.MapHttpHandlerRoute("DoSomething", "Handlers/DoSomething", "~/DoSomething.ashx");

// using the type of the handler
routes.MapHttpHandlerRoute<MyHttpHanler>("DoSomething", "Handlers/DoSomething");

And that's it! :)

4 comments:

BuildItWithStraw said...

IS there a VB version of this?

BuildItWithStraw said...
This comment has been removed by a blog administrator.
Alexandre Simoes said...

I'm sorry for the delay mate.
I don't have any VB.net version of it but it should be easy to convert using any online C# to VB converter.

Try this one and let me know:
http://www.developerfusion.com/tools/convert/csharp-to-vb/

Cheers,
Alex

Konstantin S said...

How can I use this with parameters?

handler:
DoSomething.ashx?first=1&second=2

I want to get URL like this:
Handlers/DoSomething/1/2