C# 在操作中为请求的其余部分设置区域性

C# 在操作中为请求的其余部分设置区域性,c#,asp.net-core,globalization,culture,C#,Asp.net Core,Globalization,Culture,我们的应用程序显示发票数据,因此URL类似于https://localhost/Invoices/guid-goes-here 因此,在处理此请求的操作中,我检索发票数据。该数据中包括了商店中使用的文化 显示发票数据(并因此支付发票)是一个单独的web应用程序,我想将用于显示发票的视图的区域性设置为使用与发票匹配的区域性 然而,到目前为止,我所发现的唯一一种为每个请求设置区域性的方法是使用中间件从URL读取区域性。我不想在URL中使用文化 我还没有找到一个方法来做这件事。以新的异步方式aspne

我们的应用程序显示发票数据,因此URL类似于https://localhost/Invoices/guid-goes-here

因此,在处理此请求的操作中,我检索发票数据。该数据中包括了商店中使用的文化

显示发票数据(并因此支付发票)是一个单独的web应用程序,我想将用于显示发票的视图的区域性设置为使用与发票匹配的区域性

然而,到目前为止,我所发现的唯一一种为每个请求设置区域性的方法是使用中间件从URL读取区域性。我不想在URL中使用文化

我还没有找到一个方法来做这件事。以新的异步方式aspnet核心工作,这可能吗?我正在使用.NET5

我想要的是:

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);
  }
}
公共类InvoiceController
{
[路由(“{id}”]
公共异步任务索引(Guid id)
{
var发票=等待_apiClient.InvoiceAsync(id);
//这是我想做的
SetCultureTo(发票文化);
//视图和部分现在都应该具有资源的区域性设置
返回视图(发票);
}
}
但由于该方法是异步的,并且所有视图都在不同的线程上呈现,因此简单地设置CurrentCulture并不能实现我希望它实现的功能


谢谢!

您可以通过分配
CultureInfo
参数直接设置区域性,如下所示:

public void SetCulture(CultureInfo-CultureInfo)
{
CultureInfo.CurrentCulture=CultureInfo;
CultureInfo.CurrentUICulture=CultureInfo;
CultureInfo.DefaultThreadCurrentCulture=CultureInfo;
}
如果要恢复到原始区域性,请创建一个类来执行切换和恢复:

公共密封类CultureSwitcher:IDisposable
{
私有只读文化信息-原创文化;
公共文化开关(字符串文化)
{
_originalCulture=CultureInfo.CurrentCulture;
var cultureInfo=String.IsNullOrEmpty(区域性)
?CultureInfo.CurrentCulture
:新文化资讯(文化);
SetCulture(cultureInfo);
}
私有void SetCulture(CultureInfo CultureInfo)
{
CultureInfo.CurrentCulture=CultureInfo;
CultureInfo.CurrentUICulture=CultureInfo;
CultureInfo.DefaultThreadCurrentCulture=CultureInfo;
}
公共空间处置()
{
SetCulture(_originalCulture);
}
}
并按如下方式使用:

使用(var cs=new CultureSwitcher(“en”))
{
//在指定的文化中做任何事情。。。
}
//在这里,它将恢复到原来的文化
参考:


我成功地获得了我想要的结果,但不是以我想要的方式。它可能没有它应该的那么健壮,但它适合我的场景

所以我最终使用了中间件选项

早些时候,我没有注意到不同的Startup.cs方法:

public void ConfigureServices(IServiceCollection services) {}

互动

我发现的所有例子都建议这样做:

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
{
    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);       
    }
}
公共类CustomCultureProvider:RequestCultureProvider { 专用只读IApiClient\u客户端; 公共CustomCultureProvider(IapClient客户端) { _客户=客户; } 公共异步重写任务确定ProviderCultureResult(HttpContext HttpContext) { var urlParts=httpContext.Request.Path.ToString().Split(新[]{'/'},StringSplitOptions.RemoveEmptyEntries); var-invoiceId=urlParts.FirstOrDefault(p=>Guid.TryParse(p,out-var-invoiceId)); 如果(!string.IsNullOrEmpty(invoiceId)) { var invoice=await_client.InvoiceAsync(新Guid(invoiceId)); 返回新的ProviderCultureResult(发票区域性); } 返回默认值(ProviderCultureResult); } } 是的,这很有效!从请求路径获取Guid有点猜测,我不喜欢


我不会将此标记为一个答案,因为这是一个解决方案,不是一个答案。我非常愿意听取关于如何改进此问题的建议,当然,我仍在寻找原始问题的答案。但目前我已经准备好了此选项。

它不起作用:(在我的视图中,在操作中设置CurrentCulture和CurrentUICulture后,将其重置回默认值。DefaultThreadCurrentCulture保持正确设置,但在我设置此值时为空,似乎没有任何影响。您可以在问题中提供更多详细信息吗?添加一些您所做工作的代码?我添加了一点。)理想情况下,这是我想要实现的代码。谢谢。这有帮助吗?:你可以添加一些代码,说明它是如何为你工作的,并且你希望它能够帮助你be@KirkLarkin这就是我用来获取我所拥有的,这是一个中间件选项,它从请求的URL读取区域性,然后进行设置om控制器中的操作。
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));
    }
}
    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);       
    }
}