I am using the following article Addition to ASP.NET MVC Localization - Using routing to support multi-culture routes.
If you look at section "Registering routes" you will see that current routes are updated (in the "RegisterRoutes" method) with the "{culture}" segment.
The difference is that I want to keep the current routes and add a duplicate for each one with a "{culture}" segment, so for a route like "foo/bar" I would get a duplicate "{culture}/foo/bar".
You can see I'm also making sure the new route comes first .
public static void MapMvcMultiCultureAttributes(this RouteCollection routes, bool inheritedRoutes = true, string defaultCulture = "en-US", string cultureCookieName = "culture")
{
routes.MapMvcAttributeRoutes(inheritedRoutes ? new InheritedRoutesProvider() : null);
var multiCultureRouteHandler = new MultiCultureMvcRouteHandler(defaultCulture, cultureCookieName);
var initialList = routes.ToList();
routes.Clear();
foreach (var routeBase in initialList)
{
var route = routeBase as Route;
if (route != null)
{
if (route.Url.StartsWith("{culture}"))
{
continue;
}
var cultureUrl = "{culture}";
if (!String.IsNullOrWhiteSpace(route.Url))
{
cultureUrl += "/" + route.Url;
}
var cultureRoute = routes.MapRoute(null, cultureUrl, null, new
{
culture = "^\\D{2,3}(-\\D{2,3})?$"
});
cultureRoute.Defaults = route.Defaults;
cultureRoute.DataTokens = route.DataTokens;
foreach (var constraint in route.Constraints)
{
cultureRoute.Constraints.Add(constraint.Key, constraint.Value);
}
cultureRoute.RouteHandler = multiCultureRouteHandler;
route.RouteHandler = multiCultureRouteHandler;
}
routes.Add(routeBase);
}
}
The "InheritedRoutesProvider" looks like this:
private class InheritedRoutesProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(ActionDescriptor actionDescriptor)
{
return actionDescriptor.GetCustomAttributes(typeof(IDirectRouteFactory), true)
.Cast<IDirectRouteFactory>()
.ToArray();
}
}
My controller looks like this:
public class MyBaseController: Controller
{
[HttpGet]
[Route("bar")]
public virtual ActionResult MyAction(){
{
return Content("Hello stranger!");
}
}
[RoutePrefix("foo")]
public class MyController: MyBaseController
{
}
My "RegisterRoutes" method looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcMultiCultureAttributes();
routes.LowercaseUrls = true;
}
Now, if I do:
- /foo/bar - WORKS!
- /en-US/foo/bar - HttpException A public action method 'MyAction' was not found on controller 'MyController'