I have a localization for 3 languages on my web app, scenario is this: When user opens up the page, URL example.com but I want to make it example.com/en.
I am trying to achieve it by using RedirectToRouteResult
but on the first try when I open the page, I get error. I have taken the mechanism from this article
The main reason why I am trying to achieve this is the user-level defined culture info, so that when user from one country sets his/her language, his/her won't have to re-do it every time they enter the page, since I am storing the data in cache and database;
And OutputCache
So that when someone enters the page they won't face other users rendered page which might not the default language for the new user.
public class InternationalizationAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// This is a dummy constraint, if the culture is zz, it means that URL does not contain correct culture
bool redirectToLanguagedVersion = filterContext.RouteData.Values["culture"].ToString() == "zz";
string language = "en", culture = "GB";
if (redirectToLanguagedVersion)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
var user = IdentityManager.GetUser(filterContext.HttpContext.User.Identity.GetUserId());
language = user.CultureInfoLanguage ?? language;
culture = user.CultureInfoCulture ?? culture;
}
else
{
language = filterContext.RequestContext.HttpContext.Cache["UserCultureInfoLanguage"]?.ToString() ?? language;
culture = filterContext.RequestContext.HttpContext.Cache["UserCultureInfoCulture"]?.ToString() ?? culture;
}
RouteValueDictionary values = filterContext.RouteData.Values;
values.Remove("culture");
values.Add("culture", culture);
filterContext.Result = new RedirectToRouteResult("DefaultWithCulture", values); // Issue hits here
}
else
{
// ... Define the culture user should use and update cache/db if needed
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture));
}
}}
And this is RouteConfig
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Call to register your localized and default attribute routes
routes.MapLocalizedMvcAttributeRoutes(
urlPrefix: "{culture}/",
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "DefaultWithCulture",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { culture = "zz", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "TourWithCulture",
url: "{culture}/{controller}/{action}/{id}/{title}",
defaults: new { controller = "Tours", action = "Explore", id = UrlParameter.Optional, title = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "Tour",
url: "{controller}/{action}/{id}/{title}",
defaults: new { controller = "Tours", action = "Explore", id = UrlParameter.Optional, title = UrlParameter.Optional },
constraints: new { culture = new CultureConstraint(defaultCulture: "zz", pattern: "[a-z]{2}") }
);
}
}