ASP.Net 核心 CookieRequestCultureProvider 不工作
ASP.Net Core CookieRequestCultureProvider not working
我有一个 ASP.Net Core 3.1 应用程序,具有以下 startup.cs(我根据网络搜索尝试了以下配置的各种组合):
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<RequestLocalizationOptions>(options =>
{
options.RequestCultureProviders = new[] { new CookieRequestCultureProvider() };
});
和
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
并且在我的应用程序的登录方法中,我将 Culture Cookie 设置如下:
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture([logged-in-user].CultureCode)));
在后续请求中,我可以在我的浏览器开发工具网络选项卡中看到 cookie:
然而,在服务器上,任何给定的请求仍然为我的开发环境维护默认服务器文化(即 en-ZA
)。 (我通过检查服务器操作方法中的任何断点中的 System.Threading.Thread.CurrentThread.CurrentCulture.Name
看到了这一点)
我 运行 遇到客户端和服务器之间的日期转换问题(例如,根据上面的屏幕截图,具有 en-US
文化的客户端)发送日期 3/5/2009 (3 月 5 日)到服务器,服务器将其解释为 5 月 3 日。
为什么我的服务器不支持 CultureCookie?我错过了什么?
如您所述,您已在 ConfigureServices
方法中注册了本地化服务。
我建议的方法是像这样使用它:
services.AddLocalization(options => options.ResourcesPath = "Resources");
services
.AddControllersWithViews()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
但不要忘记注册中间件:
// In StartUp.cs Configure method
var SupportedCultures = new CultureInfo[]
{
new CultureInfo("en"),
new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(defaultLanguage),
SupportedCultures = SupportedCultures,
SupportedUICultures = SupportedCultures
});
关于您的 cookie 结束时间问题,请尝试指定您的 cookie 的结束日期。像这样:
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions
{
Expires = DateTimeOffset.UtcNow.AddYears(1),
SameSite = SameSiteMode.None
});
我在 asp.net 核心 6.0.
感谢Anduin
的回复,对我帮助很大! official doc 具有误导性。
我发现对我来说关键点是:
- 服务配置:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("zh-CN")
};
options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
- 应用支持:
var SupportedCultures = new[]
{
new CultureInfo("en"),
new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"),
SupportedCultures = SupportedCultures,
SupportedUICultures = SupportedCultures
});
- 具有语言名称但没有 ISO 代码的资源文件:
.\Resources\Controllers\HomeController.zh.resx
.\Resources\Views\Home\Index.zh.resx
- 使用 Ajax 以编程方式更改区域性(我添加了一个空默认值):
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options
@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = new List<SelectListItem>();
cultureItems.Add(new SelectListItem { Value = "", Text = Localizer["Select Lang"].Value });
cultureItems.AddRange(LocOptions.Value.SupportedUICultures
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList());
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<form id="selectLanguage" asp-controller="Home"
asp-action="SetLanguage" asp-route-returnUrl="@returnUrl"
method="post" class="form-horizontal" role="form">
<label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label>
<select name="culture" onchange="this.form.submit();" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
</select>
</form>
</div>
[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);
}
- IStringLocalizer(我保留了可移动的 _logger):
private readonly ILogger<HomeController> _logger;
private readonly IStringLocalizer<HomeController> _localizer;
public HomeController(ILogger<HomeController> logger, IStringLocalizer<HomeController> localizer)
{
_localizer = localizer;
_logger = logger;
}
public IActionResult Index()
{
ViewData["Message"] = _localizer["Test Text"];
return View();
}
- index.cshtml 中的 IViewLocalizer:
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["Title Text"];
}
并在资源文件中定义键Test Text
和Title Text
。
我有一个 ASP.Net Core 3.1 应用程序,具有以下 startup.cs(我根据网络搜索尝试了以下配置的各种组合):
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<RequestLocalizationOptions>(options =>
{
options.RequestCultureProviders = new[] { new CookieRequestCultureProvider() };
});
和
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
并且在我的应用程序的登录方法中,我将 Culture Cookie 设置如下:
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture([logged-in-user].CultureCode)));
在后续请求中,我可以在我的浏览器开发工具网络选项卡中看到 cookie:
然而,在服务器上,任何给定的请求仍然为我的开发环境维护默认服务器文化(即 en-ZA
)。 (我通过检查服务器操作方法中的任何断点中的 System.Threading.Thread.CurrentThread.CurrentCulture.Name
看到了这一点)
我 运行 遇到客户端和服务器之间的日期转换问题(例如,根据上面的屏幕截图,具有 en-US
文化的客户端)发送日期 3/5/2009 (3 月 5 日)到服务器,服务器将其解释为 5 月 3 日。
为什么我的服务器不支持 CultureCookie?我错过了什么?
如您所述,您已在 ConfigureServices
方法中注册了本地化服务。
我建议的方法是像这样使用它:
services.AddLocalization(options => options.ResourcesPath = "Resources");
services
.AddControllersWithViews()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
但不要忘记注册中间件:
// In StartUp.cs Configure method
var SupportedCultures = new CultureInfo[]
{
new CultureInfo("en"),
new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(defaultLanguage),
SupportedCultures = SupportedCultures,
SupportedUICultures = SupportedCultures
});
关于您的 cookie 结束时间问题,请尝试指定您的 cookie 的结束日期。像这样:
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions
{
Expires = DateTimeOffset.UtcNow.AddYears(1),
SameSite = SameSiteMode.None
});
我在 asp.net 核心 6.0.
感谢Anduin
的回复,对我帮助很大! official doc 具有误导性。
我发现对我来说关键点是:
- 服务配置:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("zh-CN")
};
options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
- 应用支持:
var SupportedCultures = new[]
{
new CultureInfo("en"),
new CultureInfo("zh")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en"),
SupportedCultures = SupportedCultures,
SupportedUICultures = SupportedCultures
});
- 具有语言名称但没有 ISO 代码的资源文件:
.\Resources\Controllers\HomeController.zh.resx
.\Resources\Views\Home\Index.zh.resx
- 使用 Ajax 以编程方式更改区域性(我添加了一个空默认值):
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options
@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = new List<SelectListItem>();
cultureItems.Add(new SelectListItem { Value = "", Text = Localizer["Select Lang"].Value });
cultureItems.AddRange(LocOptions.Value.SupportedUICultures
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList());
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<form id="selectLanguage" asp-controller="Home"
asp-action="SetLanguage" asp-route-returnUrl="@returnUrl"
method="post" class="form-horizontal" role="form">
<label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label>
<select name="culture" onchange="this.form.submit();" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
</select>
</form>
</div>
[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);
}
- IStringLocalizer(我保留了可移动的 _logger):
private readonly ILogger<HomeController> _logger;
private readonly IStringLocalizer<HomeController> _localizer;
public HomeController(ILogger<HomeController> logger, IStringLocalizer<HomeController> localizer)
{
_localizer = localizer;
_logger = logger;
}
public IActionResult Index()
{
ViewData["Message"] = _localizer["Test Text"];
return View();
}
- index.cshtml 中的 IViewLocalizer:
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["Title Text"];
}
并在资源文件中定义键Test Text
和Title Text
。