我已经设法得到了我想要的结果,但不是以我想要的方式。它可能没有应有的强大,但它适用于我的场景。
所以我最终还是使用了中间件选项。
我之前没有注意到的一点(我对 .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 有点猜测。
我不会将此标记为答案,因为这是一种解决方法,而不是答案。我非常愿意接受有关如何改进这一点的建议,当然仍在寻找原始问题的答案。但现在我已经做好了。