Practical ASP.NET

Supporting Routing

Want to make life easier for your users? NET 3.5 SP1's routing technology has some extra features to let you do just that.

In two previous columns ("Routing Your ASP.NET Application" and "Decoding Routes"), I looked at how you can configure your site to disconnect the URLs that your users will provide from the virtual paths to your pages. This column goes beyond those basics to look at some additional features of routing. The goals here are to simplify your code and make life easier for your users.

When you set up a route, you specify a template for the URL that users will provide. The template that I've been using looks like this:

Inventory/{action}/{itemid}

A sample URL with "Details" plugged into the action parameter and "A1234" plugged into the itemid would look like this:

http://www.mysite.com/MyApp/Inventory/Details/A1234

Simplifying Your Code
The first issue to address is that not all URLs that users can provide will be valid. For instance, for the action parameter, I'm only willing to accept "Details" and "List." I could check for those entries by adding more code to the class that decodes URLs, but a better solution is to let the Routing object do it by setting a constraint. If you specify a constraint and the user enters an invalid URL, the user gets back the standard HTTP 404 error.

The Constraints property on a Route object accepts a RouteValueDictionary object. When you create a RouteValueDictionary object, you pass a new anonymous type with properties that correspond to your template's parameters. You use regular expression syntax to specify valid entries for each of your parameters.

This example creates a constraint that specifies that my action parameter must be either "List" or "Details"; my itemid must either begin with the letter A and be followed by four digits or be the word "All":

Dim rvd As Routing.RouteValueDictionary 
rvd = New Routing.RouteValueDictionary(New With _
   {.action = "Details|List", .itemid = "[A]\d{4}|All"})
rt.Constraints = rvd

Going back to the code in a previous column ("Decoding Routes") I can now eliminate the code that checked for invalid entries in the action parameter -- those URLs will no longer be passed to my decoder. Of course, just because you can use a constraint to prevent invalid entries, doesn't mean you should stop there. The 404 error message doesn't give the user much help in figuring out what a valid URL should look like. Now that you're providing users with meaningful URLs, you can use IIS' ability to specify custom error pages to send users a page that describes what a valid URL looks like.

Most of the time, all the data that your decoding process will need will be provided by the user's entries to your URL template. However, you may occasionally need data that's available at the time that the Route is created. The DataTokens property is designed to provide you with a place to attach additional information to a route when you define it.

The DataTokens property on the Route object also accepts RouteValueDictionary object. When decoding the route, you can access that value by name and use it for, well, whatever you need. Effectively, the DataTokens property functions like the Tag property that many user interface controls include that provide the developer with a place to store data that doesn't affect the way that the control behaves.

This code, for instance, attaches the date and time that the Route was created to the Route as a DataToken named "dateCreated":

rvd = New Routing.RouteValueDictionary(New With _
   {.dateCreated = Now()})
rt.DataTokens = rvd

You can retrieve any DataTokens by name in the class that decodes your Routes through the requestContext parameter's DataTokens collection, as this example does:

Dim dt As DateTime
dt = Convert.ToDateTime( _
   requestContext.RouteData.DataTokens("dateCreated"))

Making Life Easier for Users
One other feature of the Route object lets you provide default values for your users. What happens, for instance, if a user enters a URL that omits any of the parameters for the template?

http://www.MyServer.com/MySite/Inventory

For the application that I've been describing, the appropriate page to send back might be a list of all products. The meaningful URL that would give that page would have "List" in the action parameter and "All." This code creates yet another RouteValueDictionary and supplies values for my action and itemid parameters. I then set my Route object's Defaults to this dictionary:

rvd = New Routing.RouteValueDictionary(New With _
   {.action = "List", .itemid = "All"})
rt.Defaults = rvd

With these few changes, I've simplified my routing code and made it easier for users to access the site.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube