为什么在呈现视图之前未设置请求区域性?

时间:2019-03-05 01:13:54

标签: c# cookies asp.net-core asp.net-core-mvc asp.net-core-2.1

简介:我目前在ASP.NET Core 2.1中使用视图本地化来获取视图。作为CultureProvider,我只使用CookieRequestCultureProvider.

然后,我需要动态更改请求的区域性,因此我将cookie重置为新值。但是,当未选择正确的请求区域时,我会遇到一个错误。

用例:我有一条路线/project/{city-name}-行动方法Project,路线参数为city-name。每个项目可以具有不同数量的可能语言。因此,当一个项目中的cookie设置为另一个项目中不存在的语言时,我需要将cookie重置为另一个项目的默认值(此类信息存储在数据库中)。

因此,让我们想象一下以下情形,您访问路径/project/krakow,然后将语言首选项设置为波兰语,因此请求区域设置为波兰语。然后,您决定转到另一个项目-project/ostrava,该项目的语言首选项“波兰语”不存在。

因此,我需要将Cookie重置为给定项目的默认语言,以便视图本地化可以选择正确的.resx文件。

但是,如果我重新编辑cookie,即使已设置cookie,也不会选择正确的.resx文件。只有页面刷新才能确保选择了正确的.resx文件。

为什么会发生这种现象?为什么在呈现视图之前未设置cookie?

为了确保在呈现视图之前设置cookie,我创建了自定义中间件,该中间件对以/ project开头的路径做出反应。当我在调试器中检查cookie时,我看到已设置cookie。但是,仅在刷新页面后通知更改。

设置请求区域性的方法(为简化起见,为代码缩写)

 [HttpGet]
 public IActionResult SetLanguage(string culture, string city)
 {

    if (HttpContext.Features.Get<ITrackingConsentFeature>().CanTrack)
    {
       Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
            new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1), Secure = true });
     }

     return RedirectToAction("Project", new { City = city }); 
  }

Cookie中间件

当我检查调试器时,我看到cookie设置正确。即使在浏览器中,我也看到已进行更改。

public class CookieMiddleware
{
   private readonly RequestDelegate _next;

   public CookieMiddleware(RequestDelegate next)
   {
       _next = next;
   }

   public Task Invoke(HttpContext httpContext)
   {
       if (httpContext.Request.Path.StartsWithSegments(new PathString("/project")))
       {
           var cityName = httpContext.Request.GetUri().Segments[2];
           if (!string.IsNullOrWhiteSpace(cityName))
           {
               var unitOfWork = httpContext.RequestServices.GetService(typeof(IUnitOfWork)) as IUnitOfWork;
               var projectInfo = unitOfWork.ProjectRepository.GetProjectInfo(cityName);

               httpContext.Response.Cookies.Append(
                      CookieRequestCultureProvider.DefaultCookieName,
                      CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(projectInfo.DefaultLanguageCode.ToLower())),
                      new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1), Secure = true });
             }
         }
   return _next(httpContext);
}

负责选择项目视图的动作方法

  [HttpGet("/[action]/{city:required}")]
  public IActionResult Project(string city)
  {
       //HERE IN RQF I DO NOT DETECT THAT CHANGE HAS BEEN MADE.
       //ONLY WHEN I DO REFRESH OF A PAGE, I SEE CORRECT REQUEST CULTURE COOKIE
        var rqf = Request.HttpContext.Features.Get<IRequestCultureFeature>();
        return View();
  }

已注册中间件的顺序:

语言Cookie中间件在RequestLocalization之后立即注册。我什至尝试交换这两个...没有成功。

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
     app.UseStaticFiles();
     app.UseCookiePolicy();
     app.UseRequestLocalization();
     app.UseCookieLanguageMiddleware();   // My cookie middleware
     app.UseMvc(routes =>
     {
          routes.MapRoute(
               name: "default",
               template: "{controller=Home}/{action=Index}/{id?}");
     });
}

0 个答案:

没有答案