Skip to content

Commit 4b32c8c

Browse files
committed
Reassign the underlying enumerator after calling reset to fix #61699
1 parent 9f2b088 commit 4b32c8c

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-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

+36
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
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 System.Collections;
5+
using Microsoft.AspNetCore.InternalTesting.Tracing;
46
using Microsoft.Extensions.Primitives;
57

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

0 commit comments

Comments
 (0)