The active language is determined from the url and then set on the
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
That way the translations are retrieved from the correct resource files.
When using Async action on controllers, we have a background thread, where the Thread.CurrentThread.CurrentUICulture is set back to OS default. But also on the background thread we need the correct language.
I created a TaskFactory extension to pass the culture to the background thread and it looks like this:
public static Task StartNew(this TaskFactory taskFactory, Action action, CultureInfo cultureInfo)
{
return taskFactory.StartNew(() =>
{
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
action.Invoke();
});
}
This allows me to do the following in an action controller:
[HttpPost]
public void SearchAsync(ViewModel viewModel)
{
AsyncManager.OutstandingOperations.Increment();
AsyncManager.Parameters["task"] = Task.Factory.StartNew(() =>
{
try
{
//Do Stuff
AsyncManager.Parameters["viewModel"] = viewModel;
}
catch (Exception e)
{
ModelState.AddModelError(string.Empty, ResxErrors.TechnicalErrorMessage);
}
finally
{
AsyncManager.OutstandingOperations.Decrement();
}
}, Thread.CurrentThread.CurrentUICulture);
}
public ActionResult SearchCompleted(Task task, ViewModel viewModel)
{
//Wait for the main parent task to complete. Mainly to catch all exceptions.
try { task.Wait(); }
catch (AggregateException ae) { throw ae.InnerException; }
return View(viewModel);
}
This all works perfectly, but I do have some concerns.
Is this the correct way to extend an action by setting the culture before invoking the original action ?
Does anyone know of a different way to pass te CurrentUICulture to a background thread for ASP.NET MVC Async actions ?
- Session is not an option.
- I do was thinking of using the CallContext.
Any other comments on this code ?
Thanks