When using async/await
, to avoid deadlocks, it is recommended to use ConfigureAwait(false)
to all the way down to the last layer. I understand that using ConfigureAwait(false)
will also make the current HttpContext null. Article
Below is the sample code just to understand why ConfigureAwait(false)
is not making HttpContext NULL when expected, and making it NULL when it is NOT expected.
Controller
public class MyController : Controller
{
private readonly MyService _service = new MyService();
private readonly MyMapper _mapper = new MyMapper();
public async Task<ActionResult> DoSomething()
{
var data = await _service.GetData().ConfigureAwait(false);
// EXPECTED: Below, HttpContext should NOT NULL
// ACTUAL: HttpContext is NOT NULL as expected
if (HttpContext == null)
{
throw new ArgumentNullException("context");
}
var model = _mapper.Map(data);
return View(model);
}
}
A Service that makes async call to datasource to GetData
public class MyService
{
public async Task<string> GetData()
{
// EXPECTED: HttpContext should be NULL here since we are calling
//this method from the Controller with ConfigureAwait(false)
// ACTUAL: HttpContext is NOT NULL, WHY?
if(HttpContext.Current == null)
{
throw new ArgumentNullException("context");
}
using (var client = new HttpClient())
{
var response = await client.GetAsync("http://url").ConfigureAwait(false);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
A mapper class maps the data to model
public class MyMapper
{
public MyModel Map(string data)
{
// EXPECTED: HttpContext should NOT NULL here since async call is already done.
// ACTUAL: HttpContext is NULL here. WHY?
if (HttpContext.Current == null)
{
throw new ArgumentNullException("context");
};
return new MyModel()
{
Message = data
};
}
}
The HttpContext is expected to be NULL inside MyService
and expected to be NOT NULL inside MyMapper
, but that is not the case. Please see my inline comments inside MyService
and MyMapper
You have it backwards. HttpContext.Current
will be null after the context switch, not before.
So:
// ACTUAL: HttpContext is NOT NULL, WHY?
if(HttpContext.Current == null)
{
throw new ArgumentNullException("context");
}
No, it is expected to be not null
since there hasn't been any await
so far (the parent await
does not apply).
// EXPECTED: HttpContext should NOT NULL here since async call is already done.
// ACTUAL: HttpContext is NULL here. WHY?
if (HttpContext.Current == null)
The switch happened after this line
var response = await client.GetAsync("http://url").ConfigureAwait(false);
So it is expected for it to be null
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With