@@ -5,6 +5,7 @@ namespace Microsoft.AspNetCore.Mvc.Versioning
55#endif
66{
77#if WEBAPI
8+ using Microsoft . Web . Http ;
89 using Microsoft . Web . Http . Routing ;
910#else
1011 using Microsoft . AspNetCore . Mvc . Routing ;
@@ -20,6 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.Versioning
2021 using MediaTypeWithQualityHeaderValue = Microsoft . Net . Http . Headers . MediaTypeHeaderValue ;
2122#endif
2223 using static ApiVersionParameterLocation ;
24+ using static System . StringComparison ;
2325
2426 /// <summary>
2527 /// Represents a service API version reader that reads the value from a media type HTTP header in the request.
@@ -47,34 +49,48 @@ public partial class MediaTypeApiVersionReader : IApiVersionReader
4749 /// <summary>
4850 /// Reads the requested API version from the HTTP Accept header.
4951 /// </summary>
50- /// <param name="accept">The <see cref="IEnumerable {T}">sequence </see> of Accept
52+ /// <param name="accept">The <see cref="ICollection {T}">collection </see> of Accept
5153 /// <see cref="MediaTypeWithQualityHeaderValue">headers</see> to read from.</param>
5254 /// <returns>The API version read or <c>null</c>.</returns>
5355 /// <remarks>The default implementation will return the first defined API version ranked by the media type
5456 /// quality parameter.</remarks>
55- protected virtual string ? ReadAcceptHeader ( IEnumerable < MediaTypeWithQualityHeaderValue > accept )
57+ protected virtual string ? ReadAcceptHeader ( ICollection < MediaTypeWithQualityHeaderValue > accept )
5658 {
57- var comparer = StringComparer . OrdinalIgnoreCase ;
58- var contentTypes = from entry in accept
59- orderby entry . Quality descending
60- group entry by entry . MediaType ;
59+ if ( accept == null )
60+ {
61+ throw new ArgumentNullException ( nameof ( accept ) ) ;
62+ }
6163
62- foreach ( var contentType in contentTypes )
64+ var count = accept . Count ;
65+
66+ if ( count == 0 )
6367 {
64- foreach ( var entry in contentType )
68+ return default ;
69+ }
70+
71+ var mediaTypes = accept . ToArray ( ) ;
72+
73+ Array . Sort ( mediaTypes , ByQualityDescending ) ;
74+
75+ for ( var i = 0 ; i < count ; i ++ )
76+ {
77+ #if WEBAPI
78+ var parameters = mediaTypes [ i ] . Parameters . ToArray ( ) ;
79+ var paramCount = parameters . Length ;
80+ #else
81+ var parameters = mediaTypes [ i ] . Parameters ;
82+ var paramCount = parameters . Count ;
83+ #endif
84+ for ( var j = 0 ; j < paramCount ; j ++ )
6585 {
66- foreach ( var parameter in entry . Parameters )
86+ var parameter = parameters [ j ] ;
87+
88+ if ( parameter . Name . Equals ( ParameterName , OrdinalIgnoreCase ) )
6789 {
6890#if WEBAPI
69- if ( comparer . Equals ( parameter . Name , ParameterName ) )
70- {
71- return parameter . Value ;
72- }
91+ return parameter . Value ;
7392#else
74- if ( comparer . Equals ( parameter . Name . Value , ParameterName ) )
75- {
76- return parameter . Value . Value ;
77- }
93+ return parameter . Value . Value ;
7894#endif
7995 }
8096 }
@@ -94,22 +110,25 @@ orderby entry.Quality descending
94110 {
95111 throw new ArgumentNullException ( nameof ( contentType ) ) ;
96112 }
97-
98- var comparer = StringComparer . OrdinalIgnoreCase ;
99-
100- foreach ( var parameter in contentType . Parameters )
101- {
102113#if WEBAPI
103- if ( comparer . Equals ( parameter . Name , ParameterName ) )
114+ var parameters = contentType . Parameters . ToArray ( ) ;
115+ var count = parameters . Length ;
116+ #else
117+ var parameters = contentType . Parameters ;
118+ var count = parameters . Count ;
119+ #endif
120+ for ( var i = 0 ; i < count ; i ++ )
121+ {
122+ var parameter = parameters [ i ] ;
123+
124+ if ( parameter . Name . Equals ( ParameterName , OrdinalIgnoreCase ) )
104125 {
126+ #if WEBAPI
105127 return parameter . Value ;
106- }
107128#else
108- if ( comparer . Equals ( parameter . Name . Value , ParameterName ) )
109- {
110129 return parameter . Value . Value ;
111- }
112130#endif
131+ }
113132 }
114133
115134 return null ;
@@ -128,5 +147,8 @@ public virtual void AddParameters( IApiVersionParameterDescriptionContext contex
128147
129148 context . AddParameter ( ParameterName , MediaTypeParameter ) ;
130149 }
150+
151+ static int ByQualityDescending ( MediaTypeWithQualityHeaderValue ? left , MediaTypeWithQualityHeaderValue ? right ) =>
152+ - Nullable . Compare ( left ? . Quality , right ? . Quality ) ;
131153 }
132154}
0 commit comments