Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 49d785c

Browse files
benaadamsdavidfowl
authored andcommitted
Use object indirection in HttpContextAccessor (#1066)
1 parent ea1ee2b commit 49d785c

File tree

4 files changed

+21
-22
lines changed

4 files changed

+21
-22
lines changed

src/Microsoft.AspNetCore.Http/HttpContextAccessor.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,35 @@ namespace Microsoft.AspNetCore.Http
77
{
88
public class HttpContextAccessor : IHttpContextAccessor
99
{
10-
private static AsyncLocal<(string traceIdentifier, HttpContext context)> _httpContextCurrent = new AsyncLocal<(string traceIdentifier, HttpContext context)>();
10+
private static AsyncLocal<HttpContextHolder> _httpContextCurrent = new AsyncLocal<HttpContextHolder>();
1111

1212
public HttpContext HttpContext
1313
{
1414
get
1515
{
16-
var value = _httpContextCurrent.Value;
17-
// Only return the context if the stored request id matches the stored trace identifier
18-
// context.TraceIdentifier is cleared by HttpContextFactory.Dispose.
19-
return value.traceIdentifier == value.context?.TraceIdentifier ? value.context : null;
16+
return _httpContextCurrent.Value?.Context;
2017
}
2118
set
2219
{
23-
_httpContextCurrent.Value = (value?.TraceIdentifier, value);
20+
var holder = _httpContextCurrent.Value;
21+
if (holder != null)
22+
{
23+
// Clear current HttpContext trapped in the AsyncLocals, as its done.
24+
holder.Context = null;
25+
}
26+
27+
if (value != null)
28+
{
29+
// Use an object indirection to hold the HttpContext in the AsyncLocal,
30+
// so it can be cleared in all ExecutionContexts when its cleared.
31+
_httpContextCurrent.Value = new HttpContextHolder { Context = value };
32+
}
2433
}
2534
}
35+
36+
private class HttpContextHolder
37+
{
38+
public HttpContext Context;
39+
}
2640
}
2741
}

src/Microsoft.AspNetCore.Http/HttpContextFactory.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ public void Dispose(HttpContext httpContext)
5353
{
5454
_httpContextAccessor.HttpContext = null;
5555
}
56-
57-
// Null out the TraceIdentifier here as a sign that this request is done,
58-
// the HttpContextAccessor implementation relies on this to detect that the request is over
59-
httpContext.TraceIdentifier = null;
6056
}
6157
}
6258
}

test/Microsoft.AspNetCore.Http.Tests/HttpContextAccessorTests.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIf
4444
var accessor = new HttpContextAccessor();
4545

4646
var context = new DefaultHttpContext();
47-
context.TraceIdentifier = "1";
4847
accessor.HttpContext = context;
4948

5049
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -76,7 +75,6 @@ public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIf
7675

7776
// Null out the accessor
7877
accessor.HttpContext = null;
79-
context.TraceIdentifier = null;
8078

8179
waitForNullTcs.SetResult(null);
8280

@@ -86,12 +84,11 @@ public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIf
8684
}
8785

8886
[Fact]
89-
public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIfDifferentTraceIdentifier()
87+
public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIfChanged()
9088
{
9189
var accessor = new HttpContextAccessor();
9290

9391
var context = new DefaultHttpContext();
94-
context.TraceIdentifier = "1";
9592
accessor.HttpContext = context;
9693

9794
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -121,12 +118,8 @@ public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIf
121118

122119
await checkAsyncFlowTcs.Task;
123120

124-
// Reset the trace identifier on the first request
125-
context.TraceIdentifier = null;
126-
127121
// Set a new http context
128122
var context2 = new DefaultHttpContext();
129-
context2.TraceIdentifier = "2";
130123
accessor.HttpContext = context2;
131124

132125
waitForNullTcs.SetResult(null);
@@ -142,7 +135,6 @@ public async Task HttpContextAccessor_GettingHttpContextDoesNotFlowIfAccessorSet
142135
var accessor = new HttpContextAccessor();
143136

144137
var context = new DefaultHttpContext();
145-
context.TraceIdentifier = "1";
146138
accessor.HttpContext = context;
147139

148140
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -172,7 +164,6 @@ public async Task HttpContextAccessor_GettingHttpContextDoesNotFlowIfExecutionCo
172164
var accessor = new HttpContextAccessor();
173165

174166
var context = new DefaultHttpContext();
175-
context.TraceIdentifier = "1";
176167
accessor.HttpContext = context;
177168

178169
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);

test/Microsoft.AspNetCore.Http.Tests/HttpContextFactoryTests.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,13 @@ public void DisposeHttpContextSetsHttpContextAccessorToNull()
3434

3535
// Act
3636
var context = contextFactory.Create(new FeatureCollection());
37-
var traceIdentifier = context.TraceIdentifier;
3837

3938
// Assert
4039
Assert.Same(context, accessor.HttpContext);
4140

4241
contextFactory.Dispose(context);
4342

4443
Assert.Null(accessor.HttpContext);
45-
Assert.NotEqual(traceIdentifier, context.TraceIdentifier);
4644
}
4745

4846
[Fact]

0 commit comments

Comments
 (0)