Apache Location-like behavior in ASP.NET

One thing I used to do in mod_perl under apache is use the <Location> directive to feed my PerlHandlers instead of using extensions. Not only did that mean that my apps had nice URLs like

but I would usually use paths as arguments (as is now common in REST_ful_ applications) such that

meant that i was calling the PerlHandler myapp and the PathInfo /user/add could be interpreted as arguments. Much nicer than


On the ASP.NET side, everything always seemed very file system based, giving it an almost CGI feel, even though under the hood it couldn't have been further from a CGI. Sure you could register your own extensions, but again, extensions and directories -- so filesystem.

I figured it must be possible to process request by hand and it turns out to be rather simple: In IIS just map * (not .*) to ASP.NET for your webapp and you can catch every request. And you don't have to give up on the existing ASPX, ASMX or ASHX infrastructure. Just use HttpContext.RewritePath(string path) to process the incoming requests and send them off to your regular pages or webservices.

By default you loose the path info that you'd receive in the equivalent Apache request. You can fix this with the following Application_BeginRequest code:

protected void Application_BeginRequest(Object sender, EventArgs e)
      int start = Request.ApplicationPath.Length+1;
      string path = Request.Path.Substring(start);
      string[] info = path.Split(new char[] {'/'},2);
      string handler = info[0];
      string pathinfo = "/"+info[1];
      string rewritePath = "~/"+handler+".aspx"+pathinfo;

This will take a URL such as foo.com/myapp/user/add and call myapp.aspx with PathInfo of /user/add.

Update: Ok. So this doesn't work quite as well as I'd hoped, since roundtrips will change the URL around. While it doesn't error out, the URL gets ugly again and you have to do some clean-up of your path info. Basically on postback foo.com/myapp/user/add becomes foo.com/myapp/user/add/myapp.aspx.

So somehow the action of the default form needs to be changed (not legal by default). Overriding the renderer or using Javascript seem like options. I'll post again when I have a working, non-hideous solution.