A RouteHandler for IHttpHandlers

This code has been incorporated into a new RouteMagic library I wrote which includes Source Code on CodePlex.com as well as a NuGet package!

I saw a bug on Connect today in which someone offers the suggestion that the PageRouteHandler (new in ASP.NET 4) should handle IHttpHandler as well as Page.

I don’t really agree with the suggestion because while a Page is an IHttpHandler, an IHttpHandler is not a Page. What I this person really wants is a new handler specifically for http handlers. Let’s give it the tongue twisting name: IHttpHandlerRouteHandler.

Unfortunately, it’s too late to add this for ASP.NET 4, but it turns out such a thing is trivially easy to write. In fact, here it is.

public class HttpHandlerRouteHandler<THandler> 
    : IRouteHandler where THandler : IHttpHandler, new() {
  public IHttpHandler GetHttpHandler(RequestContext requestContext) {
    return new THandler();
  }
}

Of course, by itself it’s not all that useful. We need extension methods to make it really easy to register routes for http handlers. I wrote a set of those, but will only post two examples here on my blog. To get the full set download the sample project at the very end of this post.

public static class HttpHandlerExtensions {
  public static void MapHttpHandler<THandler>(this RouteCollection routes, 
string url) where THandler : IHttpHandler, new() { routes.MapHttpHandler<THandler>(null, url, null, null); } //... public static void MapHttpHandler<THandler>(this RouteCollection routes, string name, string url, object defaults, object constraints) where THandler : IHttpHandler, new() { var route = new Route(url, new HttpHandlerRouteHandler<THandler>()); route.Defaults = new RouteValueDictionary(defaults); route.Constraints = new RouteValueDictionary(constraints); routes.Add(name, route); } }

This now allows me to register a route which is handled by an IHttpHandler very easily. In this case, I’m registering a route that will use my SimpleHttpHandler to handle any two segment URL.

public static void RegisterRoutes(RouteCollection routes) {
    routes.MapHttpHandler<SampleHttpHandler>("{foo}/{bar}");
}

And here’s the code for SampleHttpHandler for completeness. All it does is print out the route values.

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

  public void ProcessRequest(HttpContext context) {
    var routeValues = context.Request.RequestContext.RouteData.Values;
    string message = "I saw foo='{0}' and bar='{1}'";
    message = string.Format(message, routeValues["foo"], routeValues["bar"]);

    context.Response.Write(message);
  }
}

When I make a request for /testing/yo I’ll see the message

I saw foo='testing' and bar='yo'

in my browser. Very cool.

Limitation

One limitation here is that my http handler has to have a parameterless constructor. That’s not really that bad of a limitation since to register an HTTP Handler in the old way you had to make sure that the handler had an empty constructor.

However, this code that I wrote for this blog post is based on code that I added to Subtext. In that code, I am passing an IKernel (I’m using Ninject) to my HttpRouteHandler. That way, my route handler will use Ninject to instantiate the http handler and thus my http handlers aren’t required to have a parameterless constructor.

Try it out!

I’ve uploaded a sample project to my blog that requires Visual Studio 2010 Beta 2 and ASP.NET 4 Beta 2 to run. However, all the code will work against ASP.NET 3.5 SP 1 except for the SimpleHttpHandler. The RequestContext property of HttpContext is new in ASP.NET 4.

What others have said

Requesting Gravatar... Jared Roberts Nov 04, 2009 8:44 AM
# re: A RouteHandler for IHttpHandlers
Two post in as many days! Yea @haacked!
Requesting Gravatar... Haacked Nov 04, 2009 8:55 AM
# re: A RouteHandler for IHttpHandlers
@Jared ha! :) I'm on fire!
Requesting Gravatar... PK Nov 04, 2009 10:56 AM
# re: A RouteHandler for IHttpHandlers
Hi Phil,

I'm really really really embarassed to admit this ... but I'm not sure I can see _why_ we would want this?

Yes, yes .. download the code, open it up and read it, etc.... but maybe some sample idea's why we would want to have a custom RouteHandler? Could this be

a) Rss feeds (what about the built in REST stuff, into MVC2.0? format=xml/js, etc?)
b) Image handler?

?

Sorry for such a really noob question. Having a blond moment here *blush*
Requesting Gravatar... Craig Stuntz Nov 04, 2009 11:05 AM
# re: A RouteHandler for IHttpHandlers
PK: It might have been a bit clearer if Phil had written, "What I this person really wants is a new *route* handler specifically for http handlers." In other words, you want to define a route which does something other than fire off an action. It lets you use routing rather than web.config to configure handlers. The idea is that you shouldn't need to write a new route handler if you already have an http handler, of which there are a lot.
Requesting Gravatar... Haacked Nov 04, 2009 2:49 PM
# re: A RouteHandler for IHttpHandlers
Craig hits it on the nail. It's a nice way to register HTTP Handlers with more control over registration than you get with web.config.

Now why would you use an HTTP Handler over simply using an MVC controller? If I was starting an app from scratch, I probably wouldn't. I'd probably just use controllers instead of handlers.

But if I'm updating an existing app, or I have an existing http handler, this route handler could come in handy.
Requesting Gravatar... Andrei Rinea Nov 04, 2009 4:06 PM
# re: A RouteHandler for IHttpHandlers
Thanks Craig for completing the post :)
Requesting Gravatar... PK Nov 05, 2009 12:19 PM
# re: A RouteHandler for IHttpHandlers
Thanks guys for the follow up comments, also :) That cleared things up :) Cheers!!
Requesting Gravatar... Henry Wu Apr 16, 2010 1:05 PM
# re: A RouteHandler for IHttpHandlers
Hi, I get 404 on the link for the sample code.
Thanks!
Requesting Gravatar... Zac Avery Apr 18, 2010 4:10 AM
# re: A RouteHandler for IHttpHandlers
I had been using a ASPX page with no content just to send some basic output to the response stream (for a simple variables within CSS files parser system that used the MapPageRoute method) but now I have this streaming the output directly. This is so much cleaner and seems to be miles faster. I would have never thought of this solution - thank you!
Requesting Gravatar... Milky Joe Jun 29, 2010 11:42 PM
# re: A RouteHandler for IHttpHandlers
The sample code link is broken. Any chance of re-upping this?
Requesting Gravatar... 404 Jan 30, 2011 5:10 AM
# re: A RouteHandler for IHttpHandlers
404!!!!! On the SAMPLE CODE.

Not cool.
Requesting Gravatar... haacked Jan 30, 2011 5:56 AM
# re: A RouteHandler for IHttpHandlers
Source code is now on CodePlex. See my blog post about my new Route Magic library.
Requesting Gravatar... AlexCode Oct 20, 2011 9:12 AM
# re: A RouteHandler for IHttpHandlers
I just wrote an extension method that makes this much more easily.
You can call it like the following:

// using the handler url
routes.MapHttpHandlerRoute("MyControllerName", "Controllers/MyController", "~/mycontroller.ashx");

// using an instance of the handler
routes.MapHttpHandlerRoute("MyControllerName", "Controllers/MyController", new mycontroller());


Have a look on my blog for the source code: HERE
Requesting Gravatar... syntax Jan 30, 2012 8:31 PM
# re: A RouteHandler for IHttpHandlers
What i dont get is how the instance of the IHttpHandler can be reused (when IsReuseable returns true), when it is created for each request, by the IRouteHandler?

What do you have to say?

(will show your gravatar)
Please add 8 and 2 and type the answer here: