title: Non System.Web alternative to HttpContext.Current
body: <p>I'm working on a legacy ASP.NET Web API 2 project that is polluted with usages of <code>HttpContext.Current</code>. I'm trying to move the application to OWIN (ASP.NET Core is not an option at this stage) to utilize <code>Microsoft.Owin.Testing.TestServer</code>, where <code>HttpContext.Current</code> will not work because it's tightly coupled with IIS through System.Web assembly.</p>
  
  <p>So I'm trying to implement an alternative using <code>System.Net.Http.HttpRequestMessage</code> (I realize this is a different type but I believe I can refactor my way out of it). The basic idea is to add a <code>System.Net.Http.DelegatingHandler</code> to Web API which will intercept the incoming request and assign it to a static property. This property will replace usages of <code>HttpContext.Current</code>. Now, before you propose using the <code>ApiController.Request</code> property - the static field is used deep in a dependency graph, so passing it as parameter all the way from the controller would be difficult if not impossible.</p>
  
  <p>Because there are multiple requests handled in parallel, a simple static property with implicit field would not work. It would get overwritten constantly by different threads handling the requests. I could use a <code>ThreadStaticAttribute</code> but there's still a risk with <code>async</code> - if a request is handled by multiple threads, my field could end up being null (or worse yet, another request).</p>
  
  <h1>Original question</h1>
  
  <p>To mitigate this, I'm thinking of binding each request to <code>SynchronizationContext.Current</code> in a dictionary which will back the static property. Something like this:</p>
  
  <pre><code>class CurrentRequestProvider
  {
      private static readonly ConcurrentDictionary&lt;SynchronizationContext, HttpRequestMessage&gt; Requests =
        new ConcurrentDictionary&lt;SynchronizationContext, HttpRequestMessage&gt;();
  
      static HttpRequestMessage CurrentRequest
      {
        get
        {
          if (SynchronizationContext.Current is object &amp;&amp;
              Requests.TryGetValue(SynchronizationContext.Current, out var request))
          {
            return request;
          }
          return null;
        }
      }
  }
  </code></pre>
  
  <p>Then the <code>DelegatingHandler</code> is nested in <code>CurrentRequestProvider</code>, so it has access to the <code>Requests</code> dictionary:</p>
  
  <pre><code>class SetCurrentRequestHandler : DelegatingHandler
  {
      protected override async Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
      {
          try
          {
              Requests.AddOrUpdate(SynchronizationContext.Current, request, (sc, r) =&gt; request);
              /* Execute controller's actions and everything */
              return await base.SendAsync(request, cancellationToken);
          }
          finally
          {
              /* Clean up the dictionary of requests */
              Requests.TryRemove(SynchronizationContext.Current, out _);
          }
      }
  }
  </code></pre>
  
  <p>Now, onto my question to multi-threading gurus :). Is it enough to use <code>ConcurrentDictionary</code> as I did to ensure thread safety in this scenario, or should I add some extra locking in <code>CurrentRequest</code>'s getter or somewhere else? Do you spot any other potential problems with this workaround?</p>
  
  <p>Thanks in advance.</p>
  
  <h1>Update with solution</h1>
  
  <p>acelent's comment below directed me to a better approach based on <code>AsyncLocal&lt;T&gt;</code>:</p>
  
  <pre><code>class CurrentRequestProvider
  {
      private static readonly AsyncLocal&lt;HttpRequestMessage&gt; AsyncLocalRequest =
        new AsyncLocal&lt;HttpRequestMessage&gt;();
  
      static HttpRequestMessage CurrentRequest =&gt; AsyncLocalRequest.Value;
  
      class SetCurrentRequestHandler : DelegatingHandler
      {
          protected override async Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
          {
              try
              {
                  AsyncLocalRequest.Value = request;
                  /* Execute controller's actions and everything */
                  return await base.SendAsync(request, cancellationToken);
              }
              finally
              {
                  AsyncLocalRequest.Value = null
              }
          }
      }
  }
  </code></pre>
  
  <p>I don't see the need to provide extra thread-safety anymore with this approach (correct me if I'm wrong).</p>