📜 ⬆️ ⬇️

Addition to ASP.NET MVC localization - We use routing

Addition to Alex Adamyan 's previous post , dedicated to localization in ASP.NET MVC applications. Although this material belongs to ASP.NET MVC 2, it can be safely used in version 3.

In my previous post I described the possibility of localization using a session, but for real applications this is absolutely not the best way. Now I will describe a very simple and very powerful localization method, placing it in the URL using the routing mechanism.

Also, this localization method does not require a trick with OutputCache, as described in the previous post.
')
The purpose of this post is the ability to show how to get from a URL like / {culture} / {Controller} / {Action} ... in your application, a URL like / en / Home / About .

Own Route Handlers

First of all, we will have to extend the standard class MvcRouteHandler . The MultiCultureMvcRouteHandler class will be designed for routes that will take the culture value from the parameters and the SingleCultureMvcRouteHandler class (will be used as a marker, without additional implementation).

public class MultiCultureMvcRouteHandler : MvcRouteHandler { protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { var culture = requestContext.RouteData.Values["culture"].ToString(); var ci = new CultureInfo(culture); Thread.CurrentThread.CurrentUICulture = ci; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); return base.GetHttpHandler(requestContext); } } 

In the overridden GetHttpHandler method , before calling its basic implementation, we simply get the “culture” parameter from the RouteData array, create the CultureInfo object and set it as the current culture of the current stream. This is where we set the culture and will not use the Application_AcquireRequestState method in Global.asax.

 public class SingleCultureMvcRouteHandler : MvcRouteHandler {} 

As I noted, this class will only be used to highlight those routes when you need them to be independent of culture.

We register routes

Now let's go to the Global.asax file, where we have the RegisterRoutes () method that registers routes. Immediately after the last binding route, add a foreach construct as in the following example.

 public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); foreach (Route r in routes) { if (!(r.RouteHandler is SingleCultureMvcRouteHandler)) { r.RouteHandler = new MultiCultureMvcRouteHandler(); r.Url = "{culture}/" + r.Url; //Adding default culture if (r.Defaults == null) { r.Defaults = new RouteValueDictionary(); } r.Defaults.Add("culture", Culture.ru.ToString()); //Adding constraint for culture param if (r.Constraints == null) { r.Constraints = new RouteValueDictionary(); } r.Constraints.Add("culture", new CultureConstraint(Culture.en.ToString(), Culture.ru.ToString())); } } } 

Great, let's go through this code. So, for each route, we first check whether the type of handler is SingleCultureMvcRouteHandler or not. So, if we change the RouteHandler property of the current route to MultiCulture , we will need to add a prefix to the URL, add a default culture, and finally add a handler to check the value of the culture parameter.

 public class CultureConstraint : IRouteConstraint { private string[] _values; public CultureConstraint(params string[] values) { this._values = values; } public bool Match(HttpContextBase httpContext,Route route,string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { // Get the value called "parameterName" from the // RouteValueDictionary called "value" string value = values[parameterName].ToString(); // Return true is the list of allowed values contains // this value. return _values.Contains(value); } } 

And enumeration of cultures

 public enum Culture { ru = 1, en = 2 } 

Simple crop switching mechanism

To change cultures, we need a simple action that I put in the AccountController.

 public ActionResult ChangeCulture(Culture lang, string returnUrl) { if (returnUrl.Length >= 3) { returnUrl = returnUrl.Substring(3); } return Redirect("/" + lang.ToString() + returnUrl); } 

and partial view with links - CultureSwitchControl.ascx

 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> <%= Html.ActionLink("eng", "ChangeCulture", "Account", new { lang = (int)MvcLocalization.Helpers.Culture.en, returnUrl = this.Request.RawUrl }, new { @class = "culture-link" })%> <%= Html.ActionLink("", "ChangeCulture", "Account", new { lang = (int)MvcLocalization.Helpers.Culture.ru, returnUrl = this.Request.RawUrl }, new { @class = "culture-link" })%> 

A simple example of using culture

And finally, if we need a culture-independent route, all we need to do is set the RouteHandler property as a SingleCultureMvcRouteHandler , for example:

 routes.MapRoute( "AboutRoute", "About", new { controller = "Home", action = "About"} ).RouteHandler = new SingleCultureMvcRouteHandler(); 

So, everything :) Localization without using a session, without problems with OutputCache (which will be discussed in my next post) and using routing.

Here is a link to the source code (project created in VS2010)

Source: https://habr.com/ru/post/128156/


All Articles