Skip to content

Commit 016ab35

Browse files
committed
Reassign the underlying enumerator after calling reset to fix dotnet#61699
1 parent 9f2b088 commit 016ab35

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

src/Http/Http/src/HeaderDictionary.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,10 @@ void IEnumerator.Reset()
451451
{
452452
if (_notEmpty)
453453
{
454-
((IEnumerator)_dictionaryEnumerator).Reset();
454+
// The cast causes the enumerator to be copied by value so we must cast it back to the original type after resetting.
455+
var enumerator = (IEnumerator)_dictionaryEnumerator;
456+
enumerator.Reset();
457+
_dictionaryEnumerator = (Dictionary<string, StringValues>.Enumerator)enumerator;
455458
}
456459
}
457460
}

src/Http/Http/test/HeaderDictionaryTests.cs

+35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.AspNetCore.InternalTesting.Tracing;
45
using Microsoft.Extensions.Primitives;
56

67
namespace Microsoft.AspNetCore.Http;
@@ -132,4 +133,38 @@ public void ReturnsCorrectStringValuesEmptyForMissingHeaders(bool withStore)
132133
IDictionary<string, StringValues> asIDictionary = emptyHeaders;
133134
Assert.Throws<KeyNotFoundException>(() => asIDictionary["Header1"]);
134135
}
136+
137+
[Theory]
138+
public void EnumeratorResetsCorrectly()
139+
{
140+
var headers = new HeaderDictionary(
141+
new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase)
142+
{
143+
{ "Header1", "Value1" },
144+
{ "Header2", "Value2" },
145+
{ "Header3", "Value3" }
146+
});
147+
148+
var enumerator = headers.GetEnumerator();
149+
var initial = enumerator.Current;
150+
151+
Assert.True(enumerator.MoveNext());
152+
153+
var first = enumerator.Current;
154+
var last = enumerator.Current;
155+
156+
while (enumerator.MoveNext())
157+
{
158+
last = enumerator.Current;
159+
}
160+
161+
Assert.NotEqual(first, initial);
162+
Assert.NotEqual(first, last);
163+
164+
((IEnumerator)enumerator).Reset();
165+
166+
Assert.Equal(enumerator.Current, initial);
167+
Assert.True(enumerator.MoveNext());
168+
Assert.Equal(enumerator.Current, first);
169+
}
135170
}

0 commit comments

Comments
 (0)