Search code examples
c#asp.net-mvc-3twitter-bootstraprazorglobalization

Returning the same view after a layout page event in MVC3/razor


I have an MVC3 application using the razor view engine and twitter-bootsrap. In my _Layout.cshtml file, I have a dropdown with a list of supported languages and have it's onchange wired to the following code:

 public ActionResult ChangeLanguage(string langue)
 {
     CultureInfo ci = new CultureInfo(langue);
     System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
     System.Threading.Thread.CurrentThread.CurrentCulture = ci;
     return View("Index", "_Layout");
 }

It works fine, but currently always return the Index view. I would like to return whatever view was currently displayed when the user changed language. I tried:

  • return View(); //obviously doesn't work
  • return View("Index", "_Layout"); //current code, not dynamic
  • return Redirect(this.Request.UrlReferrer.AbsolutePath); //does nothing, language doesn't change either
  • passing the view as a parameter and returning it: I couldn't find an object that actually work
  • This question seems to be a possible solution start but I'm not familiar enough yet to adapt it.
  • return Redirect(Request.ServerVariables["HTTP_REFERER"]); //good page, no culture change

My question is in 2 parts:

  • How can I return the same view that the user was seeing when he changed language?
  • Where should I really put this code? It's currently using the same controller as the homepage and that doesn't feel right. Is there an equivalent to an ASP.NET webforms masterpage's codebehind file?

Solution

  • You could use the Request.ServerVariables["HTTP_REFERER"] to get the page referring page.

    public ActionResult ChangeLanguage(string langue)
    {
      CultureInfo ci = new CultureInfo(langue);
      System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
      System.Threading.Thread.CurrentThread.CurrentCulture = ci;
      var referer = Request.ServerVariables["HTTP_REFERER"];
      return Redirect(referer);
    }
    

    The way I've handled this in the past was to change the culture using an ActionFilterAttribute which I would apply to all controllers.

    public sealed class CultureActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            object value;
            // get culture
            filterContext.RouteData.TryGetValue("culture", out value);
            var cultureName = value as string;
            if (cultureName == null)
            {
                cultureName = // resolve your default culture
            }
    
            var culture = new CultureInfo(cultureName);
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
    
        }
    }
    

    (I had route constraints verify the culture before this actionfilter took affect. If you don't want to do that... because you're using querystring parametrs... the validation should probably go in this method.)