How to make HttpContext available in Task called synchronously?
<p>In my ASP.NET MVC application, I need to implement/override some intrinsic entities like <code>IModelBinder.BindModel()</code>, <code>IActionFilter.OnActionExecuting()</code>, etc. Those methods are calling an async method, but obviously I cannot turn them into <code>async Task&lt;&gt;</code> to be able to use the <code>await</code> keyword.</p>

<p>So I wrote the following "adapter":</p>

<pre class="lang-cs prettyprint-override"><code>public static T GetResult&lt;T&gt;(Func&lt;Task&lt;T&gt;&gt; func)
{
    var httpContext = HttpContext.Current;

    var proxyTask = Task.Run(() =&gt;
    {
        HttpContext.Current = httpContext;
        return func();
    });

    return proxyTask.Result;
}
</code></pre>

<p>which lets me call my async <code>GetData()</code>in a synchronous manner:</p>

<pre class="lang-cs prettyprint-override"><code>public static async Task&lt;Data&gt; GetData()
{
    if (isCached)
        return GetCachedData();

    var data = await GetOriginalData();
    SetCachedData(data);
    return data;
}

...

var data = GetResult(() =&gt; GetData());
</code></pre>

<p>Okay, it works, so I would call it a day, however as you can see, most of the time, <code>GetData()</code> runs synchronously, therefore spawning a new thread unconditionally is not good performance-wise. That was bugging me, so I have ended up with a different solution:</p>

<pre class="lang-cs prettyprint-override"><code>public static T GetResult&lt;T&gt;(Func&lt;Task&lt;T&gt;&gt; func)
{
    var syncContext = SynchronizationContext.Current;
    SynchronizationContext.SetSynchronizationContext(null);

    var task = func();

    SynchronizationContext.SetSynchronizationContext(syncContext);

    return task.Result;
}
</code></pre>

<p>It also works, however the issue is that since <code>SynchronizationContext</code> is no longer flowing in, there is no <code>HttpContext</code> available in the called method.</p>

<p>I could probably work that around by putting <code>HttpContext.Current</code> into logical <code>CallContext</code> but am still wondering if there is a better way to tackle the issue? Something like customizing <code>SynchronizationContext.Current.CreateCopy()</code>.</p>