0

I've looked at a lot of similar questions to this one but nothing has solved my issue. I persist my users language in a cookie. First, its an Umbraco site. I have a default controller that is hit for every request in order to check the language.

I do some calculations to check what language the user should be on in the controller and then set the cookie like below.

 private void SetCulture(string language, bool updateCookie)
 {
     if (updateCookie)
     {
         var newCookie = new HttpCookie("currentLanguage", language) { Expires = DateTime.Now.AddDays(30) };
         Response.Cookies.Add(newCookie);
         Request.Cookies.Add(newCookie);
     }
     System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(language);
     System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
 }

Currently I'm updating both the request and the response cookie. The issue is after I hit the controller, I load my view. In my view I use a helper to get the current cookies value, however the cookie in the request has not been updated and still holds its original value. So for example, say a user is on the EN page, they user a language switcher to change to FR, I update the cookie in the controller using the SetCulture method above which works, but in my helper class, the cookie is still set to the original EN value. The CookieHelper is below.

public static class CookieHelper
{
     public static string GetLanguageCookie()
     {
         var newCookie = HttpContext.Current.Request.Cookies["currentLanguage"];

         return newCookie?.Value ?? "en";
     }

     public static void UpdateLanguageCookie(string lang)
     {
         var newCookie = HttpContext.Current.Request.Cookies["currentLanguage"];
         if (newCookie?.Value != null)
         {
             newCookie.Value = lang;
             newCookie.Expires = DateTime.Now.AddDays(30);
         }
         else
         {
             CreateLanguageCookie(lang);
         }

      }

      public static void CreateLanguageCookie(string lang)
      {
          var newCookie = new HttpCookie("currentLanguage", lang) { Expires = DateTime.Now.AddDays(30) };
          HttpContext.Current.Response.Cookies.Add(newCookie);
      }
 }

The controller below has been cut down for just the question relevant code. Just to clarify, the website is broken up into regional sections, UK, FR, and DE. each region site has a set of allowed languages DE = "en,de" uk = "en" and fr = "fr". Strange set up I know, but I'm just following the spec. Hoping the explanation makes the code a bit clearer.

public class BaseRenderController : RenderMvcController
    {
        public override ActionResult Index(RenderModel model)
        {
            var language = Request.UserLanguages.First().ToLowerInvariant().Substring(0, 2);
            // If true it means where on the language select screen.
            if (Request.Url.Segments.Length == 1)
            {
                if (language == "en")
                {
                    SetCulture("en", false);
                }
                else if (language == "fr")
                {
                    SetCulture("fr", false);
                }
                else if (language == "de")
                {
                    SetCulture("de", false);
                }
                else
                {
                    SetCulture("en", false);
                }
            }
            else
            {
               var currentLang = CookieHelper.GetLanguageCookie();

               if (Helpers.UrlHelper.GetRegionalSegmentFromUrl().Substring(1).ToLower() == "uk")
               {
                   SetCulture("en", true);
               }
               else if (Helpers.UrlHelper.GetRegionalSegmentFromUrl().Substring(1).ToLower() == "fr")
               {
                   SetCulture("fr", true);
               }
               else if (Helpers.UrlHelper.GetRegionalSegmentFromUrl().Substring(1).ToLower() == "de")
               {
                   if (language == "de" || currentLang == "de")
                   {
                       SetCulture("de", true);
                   }
                   else
                   {
                       SetCulture("en", true);
                   }
               }
            }


            return base.Index(model);
        }

        private void SetCulture(string language, bool updateCookie)
        {
            if (updateCookie)
            {
                var newCookie = new HttpCookie("currentLanguage", language) { Expires = DateTime.Now.AddDays(30) };
                Response.Cookies.Add(newCookie);
                Request.Cookies.Add(newCookie);
            }
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(language);
            System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
        }
    }
Joe Wilson
  • 5,591
  • 2
  • 27
  • 38
Tony_89
  • 797
  • 11
  • 39
  • Can you please show the controller/actions? – Joe Wilson Feb 20 '18 at 21:30
  • @JoeWilson ive added the controller, it only used the index action. Its as though the controller and cookie helper have the current request in a different context, so updating the cookie in the controller does not effect the cookie accessed in the helper. – Tony_89 Feb 20 '18 at 21:38
  • You don't need to write the cookie to `Request.Cookies.Add(newCookie);` unless you are building up a request to send. – Joe Wilson Feb 20 '18 at 21:58
  • If the culture is already available in the URL, you don't need a cookie. See [ASP.NET MVC 5 culture in route and url](https://stackoverflow.com/a/32839796). – NightOwl888 Feb 21 '18 at 07:34

1 Answers1

0

The browser sets the cookies when it sends a request. ASP.NET provides access to the Cookies from a Request object. To set a cookie, you need to set it on the Response object. Or as Miscrosoft's documentation states:

The browser is responsible for managing cookies on a user system. Cookies are sent to the browser via the HttpResponse object that exposes a collection called Cookies. You can access the HttpResponse object as the Response property of your Page class. Any cookies that you want to send to the browser must be added to this collection.

https://msdn.microsoft.com/en-us/library/ms178194.aspx

Alex
  • 2,795
  • 3
  • 21
  • 21