How to Response.Cookies.Append() in ASP.Net Core 1

2020-04-17 07:58发布

问题:

I am trying to add Globalization to an Intranet application, using a cookie to allow users a culture preference. The middleware is set up and running but I have run into an issue with appending to the cookie based on the UI selection.

The method is straight from the Asp.Net Core documentation as below:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RequestLocalizationOptions>(
        options =>
        {
            var supportedCultures = new List<CultureInfo>
            {
            new CultureInfo("en-US"),
            new CultureInfo("en-GB"),
            new CultureInfo("fr-FR"),
            new CultureInfo("es-ES")
            };

            options.DefaultRequestCulture = new RequestCulture(culture: "en-GB", uiCulture: "en-GB");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });

    services.AddLocalization();
    services.AddMvc(config =>
    {
        var policy = new AuthorizationPolicyBuilder()
                         .RequireAuthenticatedUser()
                         .Build();
        config.Filters.Add(new AuthorizeFilter(policy));
    })
    .AddViewLocalization();

    services.AddSession(options => {
        options.CookieName = "Intranet";
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
    app.UseRequestLocalization(locOptions.Value);

    app.UseSession();
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

[HttpPost]
 public IActionResult SetLanguage(string culture, string returnUrl)
  {
    Response.Cookies.Append(
      CookieRequestCultureProvider.DefaultCookieName,
      CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) 
   });

   return LocalRedirect(returnUrl);
 }

The issues are:

  1. Response does not exist
  2. LocalRedirect does not exist

I have tried:

  1. HttpResponse, HttpRequest
  2. LocalRedirectResult

回答1:

From the docs where you got that sample, you can see that the code comes from GitHub with lots of sample projects. This particular sample comes from Localization.StarterWeb.

Your two "missing" methods are actually part of ControllerBase (which is what Controller inherits from. So if you put this action method into a controller, it will work.

public class HomeController : Controller
{
    [HttpPost]
    public IActionResult SetLanguage(string culture, string returnUrl)
    {
        Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
            new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
        );

        return LocalRedirect(returnUrl);
    }
}


回答2:

In ASP .NET Core 2.1+, if you use the cookie policy feature for implementing GDPR by invoking app.UseCookiePolicy() in Startup.cs, make sure to mark your cookie as essential, otherwise it won't be sent to users who haven't accepted your policy.

Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
            new CookieOptions 
            { 
                Expires = DateTimeOffset.UtcNow.AddYears(1), 
                IsEssential = true 
            }
        );

Obviously, you should also mention the cookie in your privacy statement.



回答3:

First of all you've to use CookieRequestCultureProvider. Later one the action you have in the example should works just fine. I would also add this:

CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;

Here is my config:

public void ConfigureServices(IServiceCollection services)
{
    services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });

    services.AddMvc()
        .AddViewLocalization(
            Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.SubFolder,
            opts => { opts.ResourcesPath = "Resources"; }
        )
        .AddDataAnnotationsLocalization();

    services.Configure<RequestLocalizationOptions>(opts =>
    {
        var supportedCultures = new[]
        {
            new CultureInfo("en-US"), 
            ...               
        };
        opts.DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en-US");
        opts.SupportedCultures = supportedCultures;
        opts.SupportedUICultures = supportedCultures;
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseRequestLocalization();

    app.UseMvc(routes =>
    {
        routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}");
    });
}