在操作中为请求的其余部分设置文化
Posted
技术标签:
【中文标题】在操作中为请求的其余部分设置文化【英文标题】:Setting the Culture for the rest of the request in an Action 【发布时间】:2021-05-17 11:59:40 【问题描述】:我们的应用程序显示发票数据,因此 URL 类似于 https://localhost/Invoices/guid-goes-here
因此,在处理此请求的操作中,我检索了发票数据。此数据中包括商店中使用的文化。
显示发票数据(并因此支付发票)是一个单独的 Web 应用程序,我想将用于显示发票的视图的文化设置为使用与发票匹配的文化。
但是,到目前为止,我发现为每个请求设置文化的唯一解决方法是使用中间件从 URL 中读取文化。我不希望 URL 中的文化。
我还没有找到方法来做到这一点。这可能以新的异步方式 aspnet 核心工作吗?我正在使用.Net 5
我想要什么:
public class InvoiceController
[Route("id"]
public async Task<IActionResult> Index(Guid id)
var invoice = await _apiClient.InvoiceAsync(id);
// Here is what I want to do
SetCultureTo(invoice.Culture);
// Views and partials should now all have culture settings for resources
return View(invoice);
但是因为该方法是异步的,并且所有视图都在不同的线程上呈现,所以简单地设置 CurrentCulture 不会做我想做的事情。
谢谢!
【问题讨论】:
这有帮助吗?:docs.microsoft.com/en-us/aspnet/core/fundamentals/… 能否请您添加一些代码说明它是如何为您工作的,并且您希望它是这样的 @KirkLarkin 这就是我用来获取我所拥有的,这是一个中间件选项,它从请求的 URL 中读取文化,然后设置它。我想要的是一种从控制器中的操作设置它的方法。 【参考方案1】:您可以通过分配CultureInfo
参数直接设置文化,如下所示:
public void SetCulture(CultureInfo cultureInfo)
CultureInfo.CurrentCulture = cultureInfo;
CultureInfo.CurrentUICulture = cultureInfo;
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
如果你想恢复到原来的文化,创建一个类来进行切换和恢复:
public sealed class CultureSwitcher : IDisposable
private readonly CultureInfo _originalCulture;
public CultureSwitcher(string culture)
_originalCulture = CultureInfo.CurrentCulture;
var cultureInfo = String.IsNullOrEmpty(culture)
? CultureInfo.CurrentCulture
: new CultureInfo(culture);
SetCulture(cultureInfo);
private void SetCulture(CultureInfo cultureInfo)
CultureInfo.CurrentCulture = cultureInfo;
CultureInfo.CurrentUICulture = cultureInfo;
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
public void Dispose()
SetCulture(_originalCulture);
并像下面这样使用它:
using(var cs = new CultureSwitcher("en"))
// do what ever in the specified culture...
// here it will be reverted back to the original culture
参考:
https://github.com/joakimriedel/culture-switcher/blob/master/src/CultureSwitcher.cs【讨论】:
它不起作用:(在我看来,CurrentCulture 和 CurrentUICulture 在 Action 中设置后被重置为默认值。DefaultThreadCurrentCulture 保持正确设置,但在我所在的位置为空设置这个,并且似乎没有任何影响。 您能否在问题中提供更多详细信息?添加一些你所做的代码? 我添加了一些看起来像我想要实现的代码,理想情况下。谢谢。【参考方案2】:我已经设法得到了我想要的结果,但不是以我想要的方式。它可能没有应有的强大,但它适用于我的场景。
所以我最终还是使用了中间件选项。
我之前没有注意到的一点(我对 .Net Core 还很陌生)是不同的 Startup.cs 方法:
public void ConfigureServices(IServiceCollection services)
和
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
互动。
我找到的所有示例,建议这样做:
public void ConfigureServices(IServiceCollection services)
services.Configure<RequestLocalizationOptions>(options =>
options.DefaultRequestCulture = ...;
options.SupportedCultures = ...;
options.SupportedUICultures = ...;
options.RequestCultureProviders.Clear();
options.RequestCultureProviders.Add(new CustomCultureProvider());
);
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseRequestLocalization();
然后在提供者中我实现了这个方法:
public class CustomCultureProvider : RequestCultureProvider
public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
var match = Regex.Match(httpContext.Request.Path, "\\/[a-zA-Z]2-[a-zA-Z]2\\/");
if (!match.Success) return Task.FromResult(default(ProviderCultureResult));
var culture = match.Value.Substring(1, 5);
return Task.FromResult(new ProviderCultureResult(culture));
我的问题是我无法访问 CultureProvider 中的 API。
我已经设法通过不在 ConfigureServices 方法中设置请求本地化选项来解决此限制。
我为 IApplicationBuilder 创建了一个扩展方法
public static void AddCustomCultureProvider(this IApplicationBuilder app)
var options = new RequestLocalizationOptions()
DefaultRequestCulture = ...,
SupportedCultures = ...,
SupportedUICultures = ...
;
var httpClient = app.ApplicationServices.GetService<IRestClient>();
var apiClient = new ApiClient(httpClient);
options.RequestCultureProviders.Clear();
options.RequestCultureProviders.Add(new CustomCultureProvider(apiClient));
app.UseRequestLocalization(options);
所以我现在可以
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.AddCustomCultureProvider();
对每个请求执行什么操作
public class CustomCultureProvider : RequestCultureProvider
private readonly IApiClient _client;
public CustomCultureProvider(IApiClient client)
_client = client;
public async override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
var urlParts = httpContext.Request.Path.ToString().Split(new [] '/' , StringSplitOptions.RemoveEmptyEntries);
var invoiceId = urlParts.FirstOrDefault(p => Guid.TryParse(p, out var invoiceId));
if (!string.IsNullOrEmpty(invoiceId))
var invoice = await _client.InvoiceAsync(new Guid(invoiceId));
return new ProviderCultureResult(invoice.Culture);
return default(ProviderCultureResult);
是的,这行得通!从我不喜欢的请求路径中获取 Guid 有点猜测。
我不会将此标记为答案,因为这是一种解决方法,而不是答案。我非常愿意接受有关如何改进这一点的建议,当然仍在寻找原始问题的答案。但现在我已经做好了。
【讨论】:
以上是关于在操作中为请求的其余部分设置文化的主要内容,如果未能解决你的问题,请参考以下文章
如何在 UITableView 中为不同的单元格和标题设置不同的随机颜色?