HttpContextAccessor behaves differently under .NETStandard1.3 vs .NET 4.5.1 #723
Description
The HttpContextAccessor
class (see here) implementation contains a compiler directive that contains a different implementation for .NETStandard1.3. The .NET 4.5.1 implementation uses CallContext
, while the .NETStandard1.3 version uses AsyncLocal<T>
under the covers.
These two versions however behave differently. While the .NET 4.5.1 version of HttpContextAccessor
is stateless, the .NETStandard version contains state in the form o an instance field. This could potentially cause a system, when deployed under .NET 4.5.1, to run fine, while completely breaking when running under .NETStandard1.3.
This will happen when an application, or third party library creates its own instance of the HttpContextAccessor
. While the stateless .NET 4.5.1 version will always request the HttpContext
from the CallContext
, the .NETStandard version will create a new async-local container per class instance. This will cause ASP.NET Core to set the HttpContext in a different bucket then where the the application or 3rd party library will read from (since it contains its own AsyncLocal<HttpContext>
instance).
This will obviously cause bugs that are really hard to track down.
The solution is to change the instance field to a class field:
static readonly AsyncLocal<HttpContext> _httpContextCurrent = new AsyncLocal<HttpContext>();