У меня есть самостоятельный хостинг OWIN размещенный веб-API, предоставляющий мне некоторые базовые методы REST.
Я хочу иметь многоязычные сообщения об ошибках, поэтому я использую Ресурс и BaseController, который устанавливает Thread.CurrentCulture и Thread.CurrentUICulture в заголовок Accept-Language запроса.
public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
if (controllerContext.Request.Headers.AcceptLanguage != null &&
controllerContext.Request.Headers.AcceptLanguage.Count > 0)
{
string language = controllerContext.Request.Headers.AcceptLanguage.First().Value;
var culture = CultureInfo.CreateSpecificCulture(language);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
base.ExecuteAsync(controllerContext, cancellationToken);
}
Все работает хорошо, но проблема возникает, если я создаю свои методы контроллера async.
Когда я использую ожидание в этом методе, он может продолжаться в другом потоке, поэтому мои CurrentCulture и CurrentUICulture теряются.
Вот небольшой пример, который я использовал, чтобы найти эту проблему.
public async Task<HttpResponseMessage> PostData(MyData data)
{
Thread currentThread = Thread.CurrentThread;
await SomeThing();
if (Thread.CurrentThread.CurrentCulture != currentThread.CurrentCulture)
Debugger.Break();
}
Я не всегда ломаю строку Debugger.Break, но большую часть времени я делаю.
Вот пример, когда я действительно использую свой Resource File.
public async Task<HttpResponseMessage> PostMyData(MyData data)
{
//Before this if I'm in the correct thread and have the correct cultures
if (await this._myDataValidator.Validate(data) == false)
//However, I might be in another thread here, so I have the wrong cultures
throw new InvalidMyDataException();
}
public class InvalidMyDataException : Exception
{
public InvalidMyDataException()
//Here I access my resource file and want to get the error message depending on the current culture, which might be wrong
: base(ExceptionMessages.InvalidMyData)
{
}
}
Некоторая дополнительная информация: у меня есть целая куча исключений, подобных этому, и все они попадают в пользовательский ExceptionFilterAttribute, который затем создает ответ.
Так что было бы очень много кода, чтобы всегда устанавливать культуру прямо перед тем, как я ее использую.