1

I'm trying to implement localization in my ASP.NET MVC application using routing.

For example: www.example.com/Home/Index - will show content for default culture. www.example.com/en/Home/Index - will show english content. www.example.com/ru/Home/Index - russian and so on...

So, I've created Localization Attribute for each action:

public class LocalizationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.RouteData.Values["lang"] != null && !String.IsNullOrWhiteSpace(filterContext.RouteData.Values["lang"].ToString()))
            {
                var lang = filterContext.RouteData.Values["lang"].ToString();
                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(lang);
                Thread.CurrentThread.CurrentUICulture =               CultureInfo.CreateSpecificCulture(lang);
            }
            else
            {
                var langHeader = String.Empty;
                langHeader = filterContext.HttpContext.Request.UserLanguages[0];
                Thread.CurrentThread.CurrentCulture =   CultureInfo.CreateSpecificCulture(langHeader);
                Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);
            }

            base.OnActionExecuting(filterContext);
        }
    }

I'm adding that attribute to every action in my controllers.

And registering routes:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
           "Localization",
           "{lang}/{controller}/{action}/{id}",
           new { lang = "en-US", controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

    routes.MapRoute(
           "Default",
           "{controller}/{action}/{id}",
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

}

Navigation to www.example.com/About/Contacts works fine. But when I navigate to www.example.com/en/About/Contacts or something like that, I get 404 error: resource not found. So, what could be the problem?

Thanks in advance for your help!

1 Answer 1

2

By navigating to www.example.com/en/About/Contacts you are actually still invoking the default route. In this case both routes will match but only the last specified one (top to bottom) will be invoked.

So when you navigate to that url the default route will assume the following: Controller: en Action: About Id: Contacts

You should add constraints to your routes to make them more specific. Or you could move the "Localization" route below the "Default" route, that way both will still match but in this case the last one will be "Localization".

If you have to troubleshoot anything similar in the future I suggest you to use the RouteDebugger NuGet package, it will help you understand which routes match a request and which one will actually execute and with which parameters.. Here's the link to Phil Haack blog entry about it: http://haacked.com/archive/2011/04/12/routedebugger-2.aspx

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much for your help! I installed RouteDebugger, and it really says the following Controller: en Action:About ID: Contacts. So, I add constraint for lang and controller: constraints: new { lang = @"^[a-z]{2}$", controller = @"^[a-zA-Z]{3,}$" } But still showing this: Controller: en Action:About ID: Contacts.
It wouldn't matter that you added a constraint to the "Localization" route as it just makes that route more specific. As I said that route you want to match do actually match, but "Default" is invoked instead as it is the latest one added to the Routes (more "important" routes at the bottom). Try switching the order of the routes or adding a (for example) numerical constraint on the Id parameter in the "Default" route, so that it will make the default route not match anymore for that specific request.
No, nothing. But i have noticed that my "Localization" route is even not displayed in RouteDebugger's "All Routes" table, where "Default" route is displayed. And if I delete "Default" route, nothing changes. Thank you for your time!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.