Introducing SmartyRoute: A smarty-ier way to do routing in ASP.NET applications
Update 9/9/2012: Scott Hanselman has just blogged about the new Friendly URL system for ASP.NET Web Forms. It's a much fancier, and admittedly much smarty-ier way to do routing and other features for Web Forms. Also, that feature will be officially supported, unlike my original sample code!
Inspired by ideas I have heard from people on my team (ideas that apparently I misunderstood!), I am introducing the new SmartyRoute, which provides a smarty-ier way to do routing in ASP.NET applications.
The basic idea is that you can make a request to a resource in an ASP.NET application without specifying a file extension in the URL. SmartyRoute will try to append a set of supported file extensions to find a handler to serve the request.
Basic Routing
In the simplest usage a user can make a request to ~/helloworld and SmartyRoute will find ~/helloworld.aspx on disk and use that as the handler. This is a very common scenario: Many developers don’t want to have file extensions in the URLs of their web sites. SmartyRoute enables developers to do that without making other changes to the application.
Slightly More Advanced Routing
A more advanced scenario is where a developer wants to have a URL such as ~/category/beverages. With the feature shown so far the developer has to have a ~/category/beverages.aspx on disk. There would also need to be another ASPX for every category in the application. However, SmartyRoute can walk up the path segments of the URL to locate a parent ASPX file. In this case SmartyRoute will detect that there is a file ~/category.aspx and load that instead. The rest of the data on the URL (in this case "beverages") can get passed in as parameters to the ASPX page.
Even More Advanced Routing
To get parameter values there are a number of helper APIs that SmartyRoute offers. The simplest way is to call SmartyRoute.GetRouteMatch().PathInfo, which will return everything after the last "/" of what was handled in the request. For example, if the user requests ~/category/beverages and it gets handled by ~/category.aspx then the remaining "beverages" value in the URL will be the path info:
string category = SmartyRoute.GetRouteMatch().PathInfo; // category == "beverages"
If the path info contains multiple segments there is an alternative API that will do some of the heavier lifting for the developer. For example, if the URL is ~/category/beverages/5 (where "5" is the page number) there are these helpers:
string category = SmartyRoute.GetNextRouteValue(); // category == "beverages" int page = SmartyRoute.GetNextRouteValue<int>(); // page == 5
Setting It Up
To use SmartyRoute in an application add a reference to the eStuff.Routing project and then go to your global.asax.cs and add this simple registration:
string[] supportedExtensions = new[] { "aspx", "ashx" }; RouteTable.Routes.Add(new SmartyRoute(supportedExtensions));
And that’s it!
Sample Project
In the attached sample project (13KB) there is the eStuff.Routing project and a sample ASP.NET Web Application Project. Open the solution in Visual Studio 2008 (with SP1) and try out these URLs:
- http://localhost:59519/Default (will load ~/default.aspx)
- http://localhost:59519/foo/bar (will load ~/foo/bar.aspx)
- http://localhost:59519/category/beverages/5/soda (will load ~/category.aspx with parameters)
- http://localhost:59519/MyHandlers/Boring (will load ~/MyHandlers/Boring.ashx handler)
- http://localhost:59519/MyHandlers/CoolStuff/Quote (will try to load ~/MyHandlers/CoolStuff/Quote.ashx handler but will fail due to web.config security)
Note that you can still make requests using the file extensions: SmartyRoute doesn’t block any current functionality (not really, anyway).
Feedback, Please!
I’d love to hear whether people find this sort of routing functionality useful. The key advantage of this simplified routing system is that you, the developer, don’t have to specify any URL route formats, yet you get most of the advantages of ASP.NET Routing: Extensionless URLs, custom data in the path info, better SEO.
Would you use this in an application that you are building?
Are you already doing something similar in an existing application?