Posts Tagged ASP.NET Routing

ASP.NET MVC URLs localization example

I have been asked to provide a working example of the technics I showed in my last two posts.
This example is about localization with the ASP.NET MVC framework using routing, a custom MvcRouteHandler, an IRouteConstraint and cultures. It demonstrates an approach how to work with URLs like mysite.com/en-US/Search.

Post #1
Post #2

Download

,

Keine Kommentare

Localization with ASP.NET MVC using Routing

In this article I am showing how to localize pages with ASP.NET MVC. Therefor I create a new Type of Route and a special RouteHandler.

Perhaps I will use ASP.NET for a new multilingual website, therefore I had to figure out how to create localized pages with ASP.NET MVC. It took a lot of time to search for some implementations, but I could not find any useable code for my problem, so here is my approach.

What I want

For my site the URL schema should look like this in general:

/{culture}/{site}

Imagine there is a page called FAQ, which is available in different languages. Here are some sample URLs for these pages:

/en-US/FAQ
/de-DE/FAQ
/de-CH/FAQ

Additional I want to have some pages which are in a single language. The backend to modify the FAQ pages for example just needs to be in English.

My approach

My idea was to automatically add the {culture} parameter to those routes, which should be multilingual. I created a new class “MultiLingualMvcRouteHandler”. This Routehandler gets the culture from RouteData and sets CurrentCulture as well as CurrentUICulture. You can use this informations in custom HTMLHelpers.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1
{
    public class MultiLingualMvcRouteHandler : MvcRouteHandler
    {
        protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
        {
            String Culture = requestContext.RouteData.Values["culture"].ToString();
            System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfoByIetfLanguageTag(Culture);
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfoByIetfLanguageTag(Culture);
            return base.GetHttpHandler(requestContext);
        }
    }
}

I also created a new Subtype of Route. Mainly this new Route is to discern between non multilingual and multilingual Routes. As you can see there are no additional methods or attributes yet.


public class MultiLangualRoute : Route
{
    public MultiLangualRoute(string url, IRouteHandler routeHandler) : base(url, routeHandler) { }
    public MultiLangualRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) : base(url, defaults, routeHandler) { }
    public MultiLangualRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) : base(url, defaults, constraints, routeHandler) { }
    public MultiLangualRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base(url, constraints, dataTokens, routeHandler) { }
}

After that I registered my FAQ page like in the global.asax. At the bottom of the method I check the RoutesCollection for Routes of my new type MultilingualRoute. The URLs of those types are expanded at the beginning with {culture}. The default culture is set to en-US.


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

    routes.Add(
        new Route("Backend/Edit/FAQ",
        new RouteValueDictionary(new { controller = "CMS", action = "Edit", Id = 1}),
        new System.Web.Mvc.MvcRouteHandler())
    );

    routes.Add(
        new MultiLangualRoute("FAQ",
        new RouteValueDictionary(new { controller = "CMS", action = "Show", Id = 1 }),
        new MvcApplication1.MultiLingualMvcRouteHandler())
    );            

    routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    );            

    foreach (Route r in routes)
    {
        if (r.GetType() == typeof(MultiLangualRoute))
        {
            r.Url = "{culture}/" + r.Url;
            r.Defaults.Add("culture", "en-US");
        }
    }
}

You can create links like this:


<%= Html.ActionLink("Show me the FAQ in German", "Show", "CMS", new {id = 1, culture="de-DE"}) %>

If you want to generate a link to a page with the actual culture, you can use the ActionLink helper without setting the culture.


<%= Html.ActionLink("Show me the FAQ", "Show", "CMS", new {id = 1}) %>

That’s it so far. Hope this is helpfull for someone else.

,

5 Kommentare