简体   繁体   中英

Razor Pages: Set cookie from _Layout.cshtml

In _Layout.cshtml I have menu to change language of the application, like:

 <nav id="nav-lang"> <ul> <li> <a href="?culture=en-EN">EN</a> </li> <li> <a href="?culture=pl-PL">PL</a> </li> </ul> </nav> 

What it does is reloading the page and sets new culture - works well. The thing is, that if the user changes culture and then go to other page within my app, default culture is loaded. I checked my options and the best choice seems to be setting a cookie "UserCulture" to eg "c=pl-PL|uic=pl-PL". The thing is I don't really know how to do it from in razor pages. I think that I should have a with asp-page-handler set to some method (eg "SetCulture") and have setting cookie in that method, but this causes some problems:

  • where to put "SetCulture" if the form would be in _Layout.cshtml? _Layout.cshtml doesn't have code behind file
  • how to submit the form from anchor ? If I put input type="submit" it ruins the look of the menu completely.. I know I could do it from js but I try to avoid js where it's not absolutely required, especially for such basic stuff..

I might be missing something very basic here, I'm quite new to Razor Pages still. From the hindsight I should have probably sticked to MVC but Razor Pages was said to be easier ..

Thanks, Brad. The solution you proposed works well. In the meantime I've got also other suggestion elsewhere and I'll post it too for anyone searching the answer in future.

In _Layout.cshtml:

<nav id="nav-lang">
    <ul>
        <li><a asp-page="/Index" asp-page-handler="SetCulture" asp-route-culture="en-EN">EN</a></li>
        <li><a asp-page="/Index" asp-page-handler="SetCulture" asp-route-culture="pl-PL">PL</a></li>
    </ul>
</nav>

In code-behind of Index (or any other page having code-behind):

public async Task<IActionResult> OnGetSetCultureAsync(string culture)
        {
            HttpContext.Response.Cookies.Append("Culture", "c=" + culture + "|uic=" + culture);
            var returnUrl = Request.Headers["Referer"].ToString();
            if (returnUrl.Contains("?culture="))
            {
                var url = returnUrl.Substring(0, returnUrl.IndexOf("?culture=")); 
                return Redirect(url + "?culture=" + culture);
            }
            else
            {
                return Redirect(returnUrl + "?culture=" + culture);
            }

        }

And of course, for both solutions to work, there must be info in Startup.cs >> Configure:

var supportedCultures = new[]
            {
                new CultureInfo("en-US"),
                new CultureInfo("pl-PL")
            };

            var lo = new RequestLocalizationOptions // Localization Options
            {
                DefaultRequestCulture = new RequestCulture("en-US"),
                SupportedCultures = supportedCultures,
                SupportedUICultures = supportedCultures
            };

            var cp = lo.RequestCultureProviders.OfType<CookieRequestCultureProvider>().First(); // Culture provider
            cp.CookieName = "Culture";

I haven't tested this out but what about setting the cookie using JavaScript and then reloading the page. The server side razor page code should check the code instead of a query parameter.

Something like the following on the _Layout page. Modify the menu to call a JS function instead of a link with a query parameter. In the JS set the cookie and reload the page.

<nav id="nav-lang">
    <ul>
        <li class="nav-item" onClick="setCulture('en-EN')">EN</li>
        <li class="nav-item" onClick="setCulture('pl-PL')">PL</li>
    </ul>
</nav>
...
<script>
    function setCulture(culture) {
        document.cookie = "culture="+culture;
        location.reload();
    }
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM