【问题标题】:Access ASP.NET Core HttpContext.Session in Custom RequestCultureProvider在自定义 RequestCultureProvider 中访问 ASP.NET Core HttpContext.Session
【发布时间】:2021-03-22 19:53:42
【问题描述】:

在我们的 ASP.NET Core Web 应用程序中,我需要能够在我编写的自定义 RequestCultureProvider 中访问 HttpContext.Session。这里有很多背景......简而言之,我只想提一下,我想要满足的业务需求是能够在我们的 Web 应用程序中以至少两种不同的文化显示数据。用户可以导航到一个页面,它应该在 fr-FR 中显示,并导航到另一个页面,它应该在 zh-CN 中显示。

当涉及到来自服务器的“响应”时,我已经完成了所有这些工作。通过在每个操作的基础上使用 ActionFilter,我可以将当​​前线程的文化设置为我想要的任何内容。我们从数据库中查找各种文化并将它们存储在 Session 中,然后存储在 ActionFilter 中,基于我传递给 ActionFilter 方法的参数...我什至可以通过各种文化中的控制器操作加载 ViewComponents 并拥有每个视图组件显示不同的文化设置。鉴于此,您可以看到为什么我不能将会话存储在 Cookie 中或使用查询字符串。

但是问题与对服务器的“请求”有关,例如当我在视图中编辑表单数据并将数据提交/发布回操作时。 当我这样做时,我的日期将作为 NULL 送回。顺便说一句,我进行模型绑定,并且在我的 ViewModels 中用这个属性标记了我的日期:

    [DataType(DataType.Date)]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd-MMM-yyyy}")]

根据下面写得很好的文章,查找Request文化的顺序是:

https://www.jerriepelser.com/blog/how-aspnet5-determines-culture-info-for-localization/

  1. 来自查询字符串
  2. 来自 cookie
  3. 来自 Accept-Language HTTP 标头
  4. 来自 RequestLocalizationOptions 类的 DefaultRequestCulture 属性
  5. 来自线程文化

我当然可以验证上述内容。如果我使用 cookie,它会起作用。如果我在 Chrome 设置中添加法语 fr-FR 作为第一语言,它就可以工作。如果我将启动本地化中的默认请求文化更改为 fr-FR,它可以工作...... 例如,在网页中,Kendo DatePicker(甚至是一个标签)将包含一个法语日期,如“14-août-2019”,但是当我将其发布回一个 Action 时,除非我设置了查询字符串,否则它是 NULL 、cookie、Accept-Language 或 DefaultRequestCulture 到 fr-FR。

一个奇怪的事情是#5说它应该使用当前的线程文化,并且在我发布表单数据的动作中我检查了当前线程的文化,它确实是fr-FR,所以我不知道为什么我的法国约会不被识别...

所以我试图解决这个问题是清除所有这些默认提供程序并编写一个自定义提供程序。 在 Startup.ConfigureServices 中,我现在这样做:

        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("en-US"),
                new CultureInfo("fr-FR"),
                new CultureInfo("zh-CN"),
                new CultureInfo("en-IE"),
            };

            var defaultCultureSettingOverride = this.Configuration.GetSection("appsettings").GetValue<string>("DefaultCultureOverride");
            defaultCultureSettingOverride = defaultCultureSettingOverride == null ? "en-US" : defaultCultureSettingOverride;

            options.DefaultRequestCulture = new RequestCulture(defaultCultureSettingOverride);
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
            options.RequestCultureProviders.Clear();
            options.RequestCultureProviders.Insert(0, new MyCustomRequestCultureProvider()
            {
                Options = options,
            });
        });

只要我的 MyCustomRequestCultureProvider 返回正确的文化,这也有效!

我现在的问题是:我需要能够在我的自定义 RequestCultureProvider 中访问会话状态。但是发送到DetermineProviderCultureResult 的HttpContext 有一个空会话。为什么?管道中的位置是否错误?

当我在 ConfigureServices 中调用 options.RequestCultureProviders.Insert(0, , new MyCustomRequestCultureProvider() 时,我还没有(据我所知)访问 HttpContextAccessor。 如果我通过 new MyCustomRequestCultureProvider(new HttpContextAccessor()),那对我没有好处... 虽然我可以访问 IHttpContextAccessor 访问器作为传递给 Startup.Configure 的参数,但我不能对 Startup.ConfigureServices 做同样的事情。如果我将(IHttpContextAccessor 访问器)作为附加参数添加到 ConfigureServices,运行时.NET Core 会出错,告诉我该方法只能访问 IServicesCollection 参数。

我在死胡同...

【问题讨论】:

    标签: asp.net-core session .net-core


    【解决方案1】:

    好吧,我的自定义 RequestCultureProvider 中的 Session 为 NULL 是我的错。

    在 Startup.Configure 中,我们有 app.UseSession() AFTER app.UseRequestLocalization()

    一旦我在 app.UseRequestLocalization() 之前移动了 app.UseSession(),我就能够在我的自定义 RequestCultureProvider 中访问 Session。

    现在,一旦我从 Session 获取用户的文化并使用它返回正确的 ProviderCultureResult,我的表单帖子确实包含日期。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-08
      • 1970-01-01
      • 2018-04-13
      • 2016-11-24
      相关资源
      最近更新 更多