There is a good solution based on IRouteConstraint . First of all, we need to create a new route mapping:
routes.MapRoute( name: "PrefixedMap", url: "{prefix}/{body}/{action}/{id}", defaults: new { prefix = string.Empty, body = string.Empty , action = "Index", id = string.Empty }, constraints: new { lang = new MyRouteConstraint() } );
The next step is to create our constraint. Before I talk about how to check relevance, as mentioned above, there are two lists with possible values, but the logic can be adjusted.
public class MyRouteConstraint : IRouteConstraint { public readonly IList<string> ControllerPrefixes = new List<string> { "stock", "bond" }; public readonly IList<string> ControllerBodies = new List<string> { "risk", "performance" }; ...
And now the Match method, which will adjust the routing as needed
public bool Match(System.Web.HttpContextBase httpContext , Route route, string parameterName, RouteValueDictionary values , RouteDirection routeDirection) { // for now skip the Url generation if (routeDirection.Equals(RouteDirection.UrlGeneration)) { return false; } // try to find out our parameters string prefix = values["prefix"].ToString(); string body = values["body"].ToString(); var arePartsKnown = ControllerPrefixes.Contains(prefix, StringComparer.InvariantCultureIgnoreCase) && ControllerBodies.Contains(body, StringComparer.InvariantCultureIgnoreCase); // not our case if (!arePartsKnown) { return false; } // change controller value values["controller"] = prefix + body; values.Remove("prefix"); values.Remove("body"); return true; }
You can play with this method more, but the concept should be clear now.
NOTE. I like your approach. Sometimes it’s much more important to extend / configure routing, then go to the code and “correct the names”. A similar solution works here: Dynamically change RouteValueDictionary
Radim Köhler
source share