Zre*_*eal 5 c# currentculture owin asp.net-web-api2 hangfire
我在 Owin 的 asp.net WebApi2 解决方案中使用 HangFire 1.6。
服务器是针对一种文化(da-DK)设置的 - 我无法更改这一点。我的应用程序必须使用另一种区域性 (en-US) 来正确解析它接收到的文本数据。基本上,我只是希望解决方案中的所有内容都使用其他区域性,并且永远不要使用服务器上的区域性。
在我的 web.config 中我有:
<system.web>
<httpRuntime targetFramework="4.6.1" />
<globalization enableClientBasedCulture="false" culture="en-US" uiCulture="en-US"/>
</system.web>
Run Code Online (Sandbox Code Playgroud)
在我的Startup Configuration方法中我有
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture;
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CurrentUICulture;
Run Code Online (Sandbox Code Playgroud)
因为有异步方法,并且我希望所有线程开始共享 web.config 中指定的相同区域性
我还在 HangFire 中运行一些经常性作业
我的问题是,无论我做什么,重复的工作都只是继续使用服务器文化(da-DK)作为 CurrentCulture (CurrentUICulture 似乎对我所做的事情做出反应:

我搜索了 Hangfire 文档等,但没有找到任何可以为我解决这个问题的方法。我宁愿避免在重复工作中使用的每个方法的顶部对文化进行硬编码
希望可以有人帮帮我...
后续(2017-11-21):
事实证明,这与 HangFire 无关。显然在运行CultureInfo.CurrentCulture时尚未设置为 web.config 中提供的值,因此此处设置为错误的值。一旦控制器执行,这些值就会设置为 web.config 中的任何内容。Startup.ConfigurationCultureInfo.DefaultThreadCurrentCulture
现在,我决定在 Startup 类中对区域性进行硬编码,以确保在执行任何 Hangfire 重复作业之前已将其设置为 DefaultThreadCurrentCulture
我们也遇到了这个问题,在 Azure 上运行时,HangFire 工作的文化RecurringJob 是 en-US 文化。这会导致日期时间解析问题(除其他外),因为我们期望我们设置的本地文化<globalization culture="en-NZ" uiCulture="en-NZ" />

如果RecurringJob是手动触发(从 HangFire Web 界面)或从控制器 ( BackgroundJob.Enqueue) 触发,则可以正确捕获区域性。
为了解决这个问题,与上面的后续 (2017-11-21)类似,我们在调用 之前将区域性强制为 web.config 中 Globalization 属性中定义的内容RecurringJob.AddOrUpdate。
我们还发现 RecurringJob 仍然使用了错误的区域性,因此我们必须首先将 CaptureCultureAttribute 替换为名为 ForceCulture 的区域性。
public static void ConfigureHangfire(this IAppBuilder app)
{
//preamble removed <snip>
app.UseHangfireServer();
//force the culture objects to be loaded from system.web/globalization
ForceCulture();
//force remove the default CaptureCultureAttribute
Hangfire.GlobalJobFilters.Filters.Remove(Hangfire.GlobalJobFilters.Filters.Where(f => f.Instance is CaptureCultureAttribute).First());
//add our one that forces the culture
Hangfire.GlobalJobFilters.Filters.Add(new ForceCultureAttribute());
//RecurringJob.AddOrUpdate...<snip>
}
private static void ForceCulture()
{
//when the RecurringJob.AddOrUpdate runs, the CultureInfo.DefaultThreadCurrentCulture is not yet set, so RecurringJobs get the wrong culture
//leading to DateTime parse issues & friends
///sf/ask/3317758951/
GlobalizationSection globalizationConfig = (GlobalizationSection)ConfigurationManager.GetSection("system.web/globalization");
var culture = new CultureInfo(globalizationConfig.Culture);
var uiCulture = new CultureInfo(globalizationConfig.UICulture);
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = uiCulture;
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = uiCulture;
}
//Taken directly from Hangfire source, with the exception of the call to ForceCulture inside OnCreating
//https://github.com/HangfireIO/Hangfire/blob/129707d66fde24dc6379fb9d6b15fa0b8ca48605/src/Hangfire.Core/CaptureCultureAttribute.cs
public sealed class ForceCultureAttribute : JobFilterAttribute, IClientFilter, IServerFilter
{
public void OnCreating(CreatingContext filterContext)
{
ForceCulture();
if (filterContext == null) throw new ArgumentNullException(nameof(filterContext));
filterContext.SetJobParameter(
"CurrentCulture", CultureInfo.CurrentCulture.Name);
filterContext.SetJobParameter(
"CurrentUICulture", CultureInfo.CurrentUICulture.Name);
}
public void OnCreated(CreatedContext filterContext)
{
}
public void OnPerforming(PerformingContext filterContext)
{
var cultureName = filterContext.GetJobParameter<string>("CurrentCulture");
var uiCultureName = filterContext.GetJobParameter<string>("CurrentUICulture");
if (!String.IsNullOrEmpty(cultureName))
{
filterContext.Items["PreviousCulture"] = CultureInfo.CurrentCulture;
SetCurrentCulture(new CultureInfo(cultureName));
}
if (!String.IsNullOrEmpty(uiCultureName))
{
filterContext.Items["PreviousUICulture"] = CultureInfo.CurrentUICulture;
SetCurrentUICulture(new CultureInfo(uiCultureName));
}
}
public void OnPerformed(PerformedContext filterContext)
{
if (filterContext == null) throw new ArgumentNullException(nameof(filterContext));
if (filterContext.Items.ContainsKey("PreviousCulture"))
{
SetCurrentCulture((CultureInfo)filterContext.Items["PreviousCulture"]);
}
if (filterContext.Items.ContainsKey("PreviousUICulture"))
{
SetCurrentUICulture((CultureInfo)filterContext.Items["PreviousUICulture"]);
}
}
private static void SetCurrentCulture(CultureInfo value)
{
#if NETFULL
System.Threading.Thread.CurrentThread.CurrentCulture = value;
#else
CultureInfo.CurrentCulture = value;
#endif
}
// ReSharper disable once InconsistentNaming
private static void SetCurrentUICulture(CultureInfo value)
{
#if NETFULL
System.Threading.Thread.CurrentThread.CurrentUICulture = value;
#else
CultureInfo.CurrentUICulture = value;
#endif
}
}
Run Code Online (Sandbox Code Playgroud)
希望这对将来的其他人有帮助!