The routing system works like a switch-case statement. The first route that matches wins, and all routes that are registered afterward are ignored.
Therefore, each route has not one, but three separate responsibilites (whether the route is an incoming HTTP request or an outgoing URL generation):
- To match the request.
- If the request matches, provide a set of route values (or a virtual path in the case of URL generation).
- If the request doesn't match, return
null
.
The code you posted does all three of these tasks.
Matching the Request
string requestedURL = string.Empty;
for (int i = 0; i < urls.Length; i++)
{
if(httpContext.Request.AppRelativeCurrentExecutionFilePath.Contains(urls[i]))
{
requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;
break;
}
}
if (!string.IsNullOrEmpty(requestedURL))
{
The above code matches the request by checking it against an array of URL values. Basically, all it says is "if the array contains the URL of the current request, it is a match".
The actual check whether it matches is the line if (!string.IsNullOrEmpty(requestedURL))
, which allows the condition to pass if the URL contains a value other than the default of String.Empty
.
Providing a Set of Route Values
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "CustomRoute");
result.Values.Add("action", "DirectCustomUrls");
result.Values.Add("customUrl", requestedURL);
The above code creates a new RouteData
object which is backed by the standard MvcRouteHandler
.
Then it populates the route values of the result. For MVC, controller
and action
are required, and the values may contain other things like primary keys, current culture, current user, etc.
Returning null
RouteData result = null;
// <snip>
if (!string.IsNullOrEmpty(requestedURL))
{
// <snip>
}
return result;
The above code sets up a pattern to ensure that when the route does not match the request, the result returned is null
.
This step is extremely important. If you don't return null in the case of a non-match, the routing engine will not check any routes registered after the current one.
Consider this route configuration:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new CustomRoute());
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
If CustomRoute
fails to return null
in the case the incoming request does not match the route, the routing framework will never check the Default
route. This makes CustomRoute
extremely inflexible because it cannot be registered before any other route in the configuration.