I solved this by adding a custom RouteInfo class which creates a new HttpContext with the supplied url and application path and uses that to obtain an instance of RouteData based on the new HttpContext object. I can then evaluate the Controller and Action values to see which route was matched. I have this wired up to an extension method on the Uri class. It feels a bit hackish and I was hoping there was a cleaner way to do this so I'll leave the question open in case someone else has a better solution.
ROUTEINFO CLASS:
public class RouteInfo { public RouteInfo(RouteData data) { RouteData = data; } public RouteInfo(Uri uri, string applicationPath) { RouteData = RouteTable.Routes.GetRouteData(new InternalHttpContext(uri, applicationPath)); } public RouteData RouteData { get; private set; } private class InternalHttpContext : HttpContextBase { private readonly HttpRequestBase _request; public InternalHttpContext(Uri uri, string applicationPath) : base() { _request = new InternalRequestContext(uri, applicationPath); } public override HttpRequestBase Request { get { return _request; } } } private class InternalRequestContext : HttpRequestBase { private readonly string _appRelativePath; private readonly string _pathInfo; public InternalRequestContext(Uri uri, string applicationPath) : base() { _pathInfo = ""; //uri.Query; (this was causing problems, see comments - Stuart) if (String.IsNullOrEmpty(applicationPath) || !uri.AbsolutePath.StartsWith(applicationPath, StringComparison.OrdinalIgnoreCase)) _appRelativePath = uri.AbsolutePath; else _appRelativePath = uri.AbsolutePath.Substring(applicationPath.Length); } public override string AppRelativeCurrentExecutionFilePath { get { return String.Concat("~", _appRelativePath); } } public override string PathInfo { get { return _pathInfo; } } } }
URI EXTENSION METHOD:
/// <summary> /// Extension methods for the Uri class /// </summary> public static class UriExtensions { /// <summary> /// Indicates whether the supplied url matches the specified controller and action values based on the MVC routing table defined in global.asax. /// </summary> /// <param name="uri">A Uri object containing the url to evaluate</param> /// <param name="controllerName">The name of the controller class to match</param> /// <param name="actionName">The name of the action method to match</param> /// <returns>True if the supplied url is mapped to the supplied controller class and action method, false otherwise.</returns> public static bool IsRouteMatch(this Uri uri, string controllerName, string actionName) { RouteInfo routeInfo = new RouteInfo(uri, HttpContext.Current.Request.ApplicationPath); return (routeInfo.RouteData.Values["controller"].ToString() == controllerName && routeInfo.RouteData.Values["action"].ToString() == actionName); } }
USAGE:
Uri url = new Uri("http://www.website.com/find-your-new-rental/northerncalifornia/sacramento.html"); if (url.IsRouteMatch("FindYourNewRental", "Community")) { // do something }
OR
if (Request.Url.IsRouteMatch("FindYourNewRental", "Community")) { // do something }
ADDED BONUS: Because the RouteInfo class gives me back an instance of RouteData, I can access the route parameters as well. This led to the creation of another Uri extension method:
public static string GetRouteParameterValue(this Uri uri, string paramaterName) { RouteInfo routeInfo = new RouteInfo(uri, HttpContext.Current.Request.ApplicationPath); return routeInfo.RouteData.Values[paramaterName] != null ? routeInfo.RouteData.Values[paramaterName].ToString() : null; }
Which can now be used like so:
string someValue = url.GetRouteParameterValue("ParameterName");