Введение : В настоящее время я использую локализацию представления в ASP.NET Core 2.1 для своих представлений.Как CultureProvider
я использую только CookieRequestCultureProvider.
Затем мне нужно динамически изменить запрашиваемую культуру, поэтому я заново устанавливаю cookie на новое значение.Однако я борюсь с ошибкой, когда не выбрана правильная культура запросов.
Вариант использования : у меня есть маршрут /project/{city-name}
- метод действия Project
с параметром маршрута city-name
.Каждый проект может иметь разное количество возможных языков.Поэтому, когда для файла cookie в проекте задан язык, которого нет в другом проекте, мне нужно заново установить для cookie значение по умолчанию для другого проекта (информация такого рода хранится в базе данных).
Итак, давайте представим следующий сценарий: у вас есть доступ к пути /project/krakow
, затем вы устанавливаете языковые предпочтения на польский язык, поэтому культура запросов устанавливается на польский.Затем вы решаете перейти в другой проект - project/ostrava
, где языкового предпочтения польского не существует.
Поэтому мне нужно переустановить cookie на язык по умолчанию для данного проекта, чтобы при локализации вида можно было выбрать правильный .resx
файл.
Однако, если я перередактирую cookie,правильный файл .resx не выбран, даже если был установлен cookie.Только обновление страницы гарантирует, что выбран правильный .resx
файл.
Почему происходит такое поведение?Почему cookie не устанавливается перед рендерингом представления?
Для обеспечения того, что cookie будет установлен перед рендерингом представления, я создал собственное Middleware, которое реагирует на путь, начинающийся с / 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?}");
});
}