Preserve HttpContext when going async with WebAPI (Medium Trust)

前端 未结 2 1189
后悔当初
后悔当初 2020-12-09 22:12

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

相关标签:
2条回答
  • 2020-12-09 22:51

    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;
    }
    
    0 讨论(0)
  • 2020-12-09 23:09

    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");
    });
    
    0 讨论(0)
提交回复
热议问题