I am building a set of ASP.Net hosted WebAPI services that must use an old library which depends heavily on HttpContext.Current. I am having trouble ensuring that context i
Context is preserved whenever you await
tasks.
What you're seeing is that there's no context for thread pool tasks (Task.Run
, TaskFactory.StartNew
, or for that matter BackgroundWorker
or Thread
or Delegate.BeginInvoke
). This is normal and expected.
So, don't use a thread pool task. Your example code seems to want to do parallel processing with multiple threads having the HttpContext
, which simply isn't possible.
You can do concurrent async
methods if you want, but this requires that your Thread.Sleep
can actually be an async
method instead of a CPU-based method:
[HttpGet]
public async Task<IEnumerable<string>> Test()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
var output = new List<string> { TestOutput("Action start") };
var task = SlowStringAsync();
output.Add(TestOutput("Action Mid"));
output.Add(await task);
output.Add(TestOutput("Action end"));
return output;
}
public async Task<string> SlowStringAsync()
{
await Task.Delay(1000);
return TestOutput("In Task");
}
If your old library is out of your control and you can't make it async
, then you'll have to call it synchronously. It's acceptable to call a synchronous method from an async
method in situations like this:
[HttpGet]
public async Task<IEnumerable<string>> Test()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
var output = new List<string> { TestOutput("Action start") };
output.Add(TestOutput("Action Mid"));
Thread.Sleep(1000);
output.Add(TestOutput("Not Really In Task"));
output.Add(TestOutput("Action end"));
return output;
}
A little noticed fact, HttpContext.Current is writable.
var context = HttpContext.Current;
var task = Task.Factory.StartNew(() => {
HttpContext.Current = context;
// You may want to set CultureInformation here too.
return TestOutput("In Task");
});