Microsoft Developer Network

Advanced ASP.NET Routing Topics

This section delves into the more intricate aspects of ASP.NET Routing, enabling you to build sophisticated and flexible web applications. Understanding these concepts will allow you to manage complex URL structures, implement custom routing logic, and optimize performance.

Custom Route Constraints

While built-in constraints like int, alpha, and guid are useful, you'll often need to define custom constraints to match specific patterns. This is crucial for validating parameters that have unique business rules or formats.

You can create custom constraints by implementing the IRouteConstraint interface. This interface requires a single method, Match, which takes the HttpContextBase, the Route, the parameter name, a dictionary of route values, and the constraint value, returning true if the constraint is met.


public class GuidConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values,HttpMethodConstraint httpMethodConstraint)
    {
        object value;
        if (values.TryGetValue(parameterName, out value) && value != null)
        {
            return Guid.TryParse(value.ToString(), out _);
        }
        return false;
    }
}
                

When defining your route, you can then apply this custom constraint:


routes.MapPageRoute(
    "ProductDetail",
    "products/{id:guid}",
    "~/Pages/ProductDetail.aspx",
    null,
    new { id = new GuidConstraint() }
);
                

Route Handlers

Route handlers are responsible for processing a request once a route has been matched. The default handler is MvcRouteHandler for MVC applications, and PageRouteHandler for Web Forms applications. You can create custom route handlers to inject custom logic into the request processing pipeline.

Implementing IRouteHandler allows you to control how requests are handled. This is powerful for scenarios like serving static content with custom headers, or integrating with different rendering engines.


public class CustomRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        // Your custom handler logic here
        return new MyCustomHandler();
    }
}
                

Attribute Routing with Constraints

Attribute routing, introduced in later versions of ASP.NET, offers a more declarative way to define routes. You can combine attribute routing with custom constraints for highly specific URL mapping.


[Route("api/orders/{orderId:int}")]
public IHttpActionResult GetOrder(int orderId) { ... }

[Route("users/{username:regex(^[a-z0-9]{3,15}$)}")]
public IHttpActionResult GetUser(string username) { ... }
                

The regex constraint is particularly useful for defining complex patterns directly in your attributes.

Route Performance and Best Practices

  • Order Matters: Define more specific routes before general ones. The routing engine evaluates routes in the order they are registered.
  • Avoid Overlapping Routes: Ensure your routes are distinct to prevent unexpected behavior.
  • Use Constraints Effectively: Constraints not only validate parameters but also help the routing engine quickly discard non-matching routes, improving performance.
  • Keep Routes Simple: While advanced features are powerful, complex routing can become difficult to maintain. Strive for clarity and simplicity where possible.
  • Default Values: Use default route values to simplify URL generation and handle optional parameters gracefully.

Handling Parameter Conflicts

When defining routes, especially with many optional parameters or similar patterns, conflicts can arise. ASP.NET Routing has a defined precedence, but it's best practice to avoid ambiguity by making route definitions unique.

If you encounter a situation where multiple routes could match a URL, the first one found in the registration order that satisfies all conditions will be selected.