5

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

Linefeed
  • 989
  • 2
  • 12
  • 18
  • This is how I've always done it, including in ASP applications. Wrap the "new thread" code in something that makes it impossible to forget to pass the thread-local state that's needed for new threads. – bzlm Sep 22 '11 at 08:26
  • Similar question http://stackoverflow.com/questions/5144314/in-net-best-way-for-keeping-currentculture-on-new-thread – Michael Freidgeim Aug 12 '12 at 08:45
  • Nice method! I only wonder: why `Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);` and not just simply assign the same `cultureInfo`? – Dirk Boer Apr 11 '14 at 12:10

1 Answers1

1

It seems the described way in the question is the answer.

Linefeed
  • 989
  • 2
  • 12
  • 18