diff --git a/src/Http/Http/src/HeaderDictionary.cs b/src/Http/Http/src/HeaderDictionary.cs index c13b2ccc567d..1713cf4be557 100644 --- a/src/Http/Http/src/HeaderDictionary.cs +++ b/src/Http/Http/src/HeaderDictionary.cs @@ -451,7 +451,10 @@ void IEnumerator.Reset() { if (_notEmpty) { - ((IEnumerator)_dictionaryEnumerator).Reset(); + // The cast causes the enumerator to be copied by value so we must cast it back to the original type after resetting. + var enumerator = (IEnumerator)_dictionaryEnumerator; + enumerator.Reset(); + _dictionaryEnumerator = (Dictionary.Enumerator)enumerator; } } } diff --git a/src/Http/Http/test/HeaderDictionaryTests.cs b/src/Http/Http/test/HeaderDictionaryTests.cs index 65a11a6dfdee..fbd1ca3dc2df 100644 --- a/src/Http/Http/test/HeaderDictionaryTests.cs +++ b/src/Http/Http/test/HeaderDictionaryTests.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; +using Microsoft.AspNetCore.InternalTesting.Tracing; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Http; @@ -132,4 +134,38 @@ public void ReturnsCorrectStringValuesEmptyForMissingHeaders(bool withStore) IDictionary asIDictionary = emptyHeaders; Assert.Throws(() => asIDictionary["Header1"]); } + + [Fact] + public void EnumeratorResetsCorrectly() + { + var headers = new HeaderDictionary( + new Dictionary(StringComparer.OrdinalIgnoreCase) + { + { "Header1", "Value1" }, + { "Header2", "Value2" }, + { "Header3", "Value3" } + }); + + var enumerator = headers.GetEnumerator(); + var initial = enumerator.Current; + + Assert.True(enumerator.MoveNext()); + + var first = enumerator.Current; + var last = enumerator.Current; + + while (enumerator.MoveNext()) + { + last = enumerator.Current; + } + + Assert.NotEqual(first, initial); + Assert.NotEqual(first, last); + + ((IEnumerator)enumerator).Reset(); + + Assert.Equal(enumerator.Current, initial); + Assert.True(enumerator.MoveNext()); + Assert.Equal(enumerator.Current, first); + } }