ASP.NET MVC routing limitations

The ASP.NET MVC stuff is pretty exciting to me, since I've been rolling my own pseudo-MVC-with-pretty-URL applications since the dawn of time (time being defined as "the release of ASP.NET").  The new MVC tools should help me do all the same things, but in a more standard way.

Last night, I set about trying to make the ASP.NET MVC stuff bend to my URL routing needs.  Unfortunately, the built in route parsing stuff is pretty basic, and it's not at all easy to replace in the current CTP.

Note: In the first public MVC preview the Route class isn't extensible (instead it is a data class). For the next preview release we are looking to make it extensible and enable developers to add scenario specific route classes (for example: a RestRoute sub-class) to cleanly add additional semantics and functionality.

My most visible home-grown implementation has URLs like these:

These URLs have a few basic components. Take the first:

/journals/apple
The content "path". Content is arranged in a hierarchy, and this path is used to locate it. Various content types have specific controllers like "Article", "Blog", etc.
.ars
This initially started out as an extension I could map to the ASP.NET handler in IIS. Since then, it's become a way of identifying the expected format for content. There are a number of those -- .rssx, for instance, will give back an RSS feed (if enabled).
/p2
/2007/12/13
/2007/12/13/final-office-2008-preview-highlights-excel-features
These chunks are basically action parameters.  The first  is a page number: a "p" followed by an integer.  The second set of parameters are: year, month and day.  Year is a 4 digit integer, while month and day are two digit integers. The third example adds a slug, which is just a string (and used to uniquely identify a post).

Ugh, parameters can't include forward slashes...

My example application above has a bunch of hierarchical data, and the standard /path/to/whatever seems like a reasonable way of representing it in a URL.  Also, it's attractive.The built in route parsing logic is dead simple, always breaks on /, and makes parameters like my "path" impossible.  I'd have to use some alternate path separator character to make it work.

...and no custom delimiters

My extensions won't work either, as they're delimited by a period.  While the file extensions started as a legacy hack, I really like using them to represent the expected content type.  It provides a bit more information about the type of URL you're requesting... or could, if you knew ".ars" was the same as ".html".In much the same vein, the "page" parameter (/p2) won't work.

Stuck with it

I've investigated techniques for hijacking the built in routing stuff, but it appears to be a pretty daunting task. The current route parsing stuff is kind of a mess (yay for CTPs). Here's a pretty chart:

 Routing diagram

The RouteTable has a RouteCollection comprised of Route objects. Route parsing and matching logic is mostly in the RouteCollection, with only a basic URL splitting function in the Route class itself. Yuck.

Ideally, the RouteCollection would hold objects that implement an IRoute interface. URL matching and RouteData extraction would be handled by those objects, leaving the RouteCollection responsible only for iterating through them and passing in URLs. It would be awesome. I suspect there are quite a few other people who might think so too.

Comment (1)

  1. Amemnted wrote::

    omg.. good work, guy

    Monday, September 22, 2008 at 1:17 pm #