gpt4 book ai didi

asp.net-core - 无法使用 ASP.NET CORE 2.2 生成用于本地化的响应 cookie

转载 作者:行者123 更新时间:2023-12-03 16:37:43 26 4
gpt4 key购买 nike

我不会对大家撒谎。我对这个问题已经无能为力了。我花了大约 4 个小时的时间尝试书中的每个解决方案来解决一个问题,我知道对于试图将本地化引入他们的 Web 应用程序的程序员来说,这个问题很常见。每当我尝试将我的网页文化从英语 (en-US) 更改为韩语 (ko-KR) 时,它都会默认恢复为默认设置的英语。我已经缩小了问题的范围,我知道我没有生成正确的响应 cookie,但我在网上找到的解决方案都没有,显然 非常常见问题对我有帮助。

我尝试刷新 cookie 和缓存,我添加了 Microsoft.AspNetCore.Localization;Microsoft.Extensions.Localization;扩展,我试过使用 isEssential CookieOptions 的参数对象,我知道我的文件结构是正确的,并且我所有的 .resx 文件都在它们应该在的位置,因为当我使用 ?culture=ko-KR 手动将网站切换到韩语时,我能够看到我应该看到的所有翻译,我相信我已经正确配置了我的startup.cs、 Controller 文件和部分 View ,我需要一个生命线。

几天前,我按照在线教程设置了一个虚拟教程 Web 应用程序,并且能够成功改变该 Web 应用程序的文化。由于 cookie 的工作方式,我只能通过更改虚拟 Web 应用程序上的语言来更改主应用程序上的语言,这根本不可行。

这是我的代码的重要部分。

启动.cs

            using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Serialization;
using Serilog;
using Snape.DataLayer.Entities;
using Snape.Web.ScheduledProcessor;
using Snape.Web.Services;
using Snape.WebSecurity.Hashing;
using Snape.WebSecurity.Helpers;
using Snape.WebSecurity.Tokens;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Threading.Tasks;
using System.Linq;

namespace Snape.Web
{
public class Startup
{
private readonly IConfiguration _configProvider;
private readonly SigningConfiguration _signConfig;
private readonly IConfigurationRoot _constantsConfigProvider;

public Startup(IConfiguration configuration)
{
_configProvider = configuration;
_signConfig = new SigningConfiguration();

// Loading Constants.json && Configuration.json
var configurationBuilder = new ConfigurationBuilder()
.AddJsonFile($"{_configProvider.GetSection("Constants").Value}", optional: false, reloadOnChange: true)
.AddJsonFile($"{_configProvider.GetSection("Version").Value}", optional: true, reloadOnChange: true);
_constantsConfigProvider = configurationBuilder.Build();

// Initializing Serilog
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
}

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
services.AddDistributedMemoryCache(); // Adds a default in-memory implementation of IDistributedCache
services.AddSession(options => options.IdleTimeout = TimeSpan.FromHours(1));

/* Note this is commented out.
var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions()
{
Path = "/",
HttpOnly = false,
IsEssential = true, //<- there
Expires = DateTime.Now.AddMonths(1),
}; */
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});


// we need to add localization to the project for views, controllers, and data annotations.
services.AddMvc()
// localization options are going to have their resources (language dictionary) stored in Resources folder.
.AddViewLocalization(opts => { opts.ResourcesPath = "Resources"; })
.AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

// we are configuring the localization service to support a list of provided cultures.
services.Configure<RequestLocalizationOptions>(opts =>
{
// the list of supported cultures.
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en"),
new CultureInfo("en-US"),
new CultureInfo("ko"),
new CultureInfo("ko-KR"),

};

// set the localization default culture as english
opts.DefaultRequestCulture = new RequestCulture("en-US");

// supported cultures are the supportedCultures variable we defined above.
// formatiting dates, numbers, etc.
opts.SupportedCultures = supportedCultures;

// UI strings that we have localized
opts.SupportedUICultures = supportedCultures;

});


services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
services.AddDbContext<SnapeDbContext>(options => options.UseLazyLoadingProxies().UseSqlite(_configProvider.GetConnectionString("SnapeDbConnection")));

services.AddSingleton(_constantsConfigProvider); // IConfigurationRoot
// *If* you need access to generic IConfiguration this is **required**
services.AddSingleton(_configProvider);
// Background task for data push
services.AddSingleton<IHostedService, DataPushingTask>();
// Background task for device's state check
services.AddSingleton<IHostedService, HeartbeatTask>();
// Background task for project's sync with cloud
services.AddSingleton<IHostedService, SyncingTask>();
// Background task for Purging
services.AddSingleton<IHostedService, PurgingTask>();
// Service for Internet Management
services.AddTransient<InternetService>();

services.Configure<TokenOptions>(_configProvider.GetSection("TokenOptions"));
var tokenOptions = _configProvider.GetSection("TokenOptions").Get<TokenOptions>();

services.AddSingleton<IPassportHasher, PasswordHasher>();
services.AddSingleton<ITokenHelper, TokenHelper>();
services.AddSingleton(_signConfig);

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
jwtBearerOptions.RequireHttpsMetadata = false;
jwtBearerOptions.SaveToken = true;
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
{
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = tokenOptions.Issuer,
ValidAudience = tokenOptions.Audience,
IssuerSigningKey = _signConfig.Key,
ClockSkew = TimeSpan.Zero
};
});
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
options.ValueLengthLimit = 1024 * 1024 * 100; // 100MB max len form data
});
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-AU");
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-AU");
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

// Enabling Logger
loggerFactory.AddSerilog();

app.UseHttpsRedirection();
app.UseStaticFiles();


// specify that globalization is being used in the pipeline.
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
app.UseCookiePolicy();

app.UseSession();
//Add JWToken to all incoming HTTP Request Header
app.Use(async (context, next) => {
var jwToken = context.Session.GetString("JWToken");
if (!string.IsNullOrEmpty(jwToken))
{
context.Request.Headers.Add("Authorization", "Bearer " + jwToken);
}
await next();
});
app.UseAuthentication();
app.UseStatusCodePages(context => {
var response = context.HttpContext.Response;
if (response.StatusCode == (int)HttpStatusCode.Unauthorized || response.StatusCode == (int)HttpStatusCode.Forbidden)
{
response.Redirect("/Account/Login");
if (Utilities.WebUtility.IsAjaxRequest(context.HttpContext.Request))
response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
return Task.CompletedTask;
});
app.UseMvc(routes => {
routes.MapRoute(
name: "default",
template: "{controller=Account}/{action=Login}/{id?}");
routes.MapRoute(
"invalid_route",
"{*url}",
new { controller = "NotFound", action = "Index" });
});
#if RELEASE
if (_constantsConfigProvider.GetValue<bool>("CELLULAR_ON"))
{
Task.Run(async () => { await app.ApplicationServices.GetRequiredService<InternetService>().Enable(); });
}
#endif
}
}
}

AccountController.cs
public class AccountController : BaseController
{
// the localizer dictionary to translate languages for this controller.
readonly IStringLocalizer<AccountController> _localizer;

readonly IConfiguration _configProvider;
readonly IPersonFacade _personFacade;
readonly SnapeDbContext _dbContext;
readonly ITokenHelper _tokenHelper;

// AccountController constructor
public AccountController(IStringLocalizer<AccountController> localizer, SnapeDbContext dbContext, IConfiguration configuration, IPassportHasher passwordHasher, ITokenHelper tokenHandler,
IConfigurationRoot constantsConfig) : base(constantsConfig)
{
// initialize the localizer.
_localizer = localizer;
_dbContext = dbContext;
_tokenHelper = tokenHandler;
_configProvider = configuration;

_personFacade = new PersonFacade(dbContext);
}

[HttpPost] // annotation that specifies that this action is called on an HTTPPost
// this method needs to persist on both this page and any subsequent ones. Sets cookie for changed culture.
public IActionResult SetLanguage(string culture, string returnURL)
{
// set the cookie on the local machine of the Http Response to keep track of the language in question.
// append the cookie and its language options.
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName, // name of the cookie
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)), // create a string representation of the culture for storage
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddDays(1),
IsEssential = true, //<- there
} // expiration after one day.
);

return LocalRedirect(returnURL); // redirect to the original URL, the account page.
}

_SelectLanguagePartial.cshtml
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Localization
@using Microsoft.Extensions.Options
@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
// this code finds out what cultures I am supporting.
// it is all defined in startup.cs
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var cultureItems = LocOptions.Value.SupportedUICultures // all the supported cultures.
.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
.ToList();

}

<!-- Partial view in ASP.NET MVC is special view which renders a portion of view content. It is just like a user control of a web form application.
Partial views can be reusable in multiple views. It helps us to reduce code duplication. In other words a partial view enables us to render a view within the parent view.
This partial view will be placed inside the layout.cshtml file, which is a shared (this is key) view that is under the wing of the home controller, just like the Home Views are -->
<!-- This code displays the culture/language dropdown.-->
<!-- Title of the dropdown-->
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<!-- another post method-->
<!-- this form will call the setLanguage method under the AccountController.cs file. Even though this is a shared view, it's shared nature means the AccountController can still see it and act off of it.-->
<form id="selectLanguage" asp-controller="Account" asp-action="SetLanguage" asp-route-returnUrl="@Context.Request.Path"
method="post" class="form-horizontal" role="form">


<!-- Select dropdown for the language selection -->
<!-- asp-for indicates -->
<a style="color:white"> @Localizer["Language"]</a>
<select name="culture" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"></select>
<button type="submit" class="btn btn-default btn-xs">Save</button>
<!-- clicking on the save button will call the action setLanguage in the AccountController.-->
</form>


</div>

部分异步调用
<!-- import the partial view for selecting languages _SelectLanguagePartial.cshtml -->
@await Html.PartialAsync("_SelectLanguagePartial");

如果有人能阐明从这里去哪里,我将不胜感激。我不想再为此拉头发了。我最后的努力是设置 isEssential = trueCookieOptions覆盖startup.cs中定义的以下请求配置
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

重要编辑:
我不知道如何或为什么,但我设法让本地化在 上工作单独 我的 Web 应用程序上的页面,访问该页面 用户使用用户名和密码成功登录。如果页面更改了我正在查找的内容,所选语言仍然存在,即使我退出登录页面也是如此。这很好,但我仍然无法从我的 Web 应用程序的登录页面更改语言或文化,其后端功能由 AccountController.cs 处理。任何人对可能导致这种奇怪现象的原因有任何想法?

最佳答案

services.AddMvc()的订单和 services.Configure<RequestLocalizationOptions>很重要。确保在 AddMvC 之前运行包括本地化在内的所有内容.

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/troubleshoot-aspnet-core-localization?view=aspnetcore-3.1 :

Localization middleware order The app may not localize because the localization middleware isn't ordered as expected. To resolve this issue, ensure that localization middleware is registered before MVC middleware. Otherwise, the localization middleware isn't applied



昨天,我在 ASP.NET Core 3.1 中构建了以下设置:

配置中的 Startup.cs
之前 .AddMvc :
app.UseRequestLocalization();

我还认为您在 RequestLocalizationOptions 中遗漏了几行:
CultureInfo[] supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("ko-KR")
};
services.Configure<RequestLocalizationOptions>(options =>
{
options.DefaultRequestCulture = new RequestCulture("en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders = new List<IRequestCultureProvider>
{
new QueryStringRequestCultureProvider(),
new CookieRequestCultureProvider()
};
});

您没有指定 CookieRequestCultureProvider它监听 cookie。这应该是您的示例不起作用的第二个原因。

关于asp.net-core - 无法使用 ASP.NET CORE 2.2 生成用于本地化的响应 cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59750992/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com