@@ -14,6 +14,21 @@ namespace Microsoft.AspNetCore.Http.Validation;
1414
1515internal static class ValidationEndpointFilterFactory
1616{
17+ // A small struct to hold the validatable parameter details to avoid allocating arrays for parameters that don't need validation
18+ private readonly struct ValidatableParameterEntry
19+ {
20+ public ValidatableParameterEntry ( int index , IValidatableInfo parameter , string displayName )
21+ {
22+ Index = index ;
23+ Parameter = parameter ;
24+ DisplayName = displayName ;
25+ }
26+
27+ public int Index { get ; }
28+ public IValidatableInfo Parameter { get ; }
29+ public string DisplayName { get ; }
30+ }
31+
1732 public static EndpointFilterDelegate Create ( EndpointFilterFactoryContext context , EndpointFilterDelegate next )
1833 {
1934 var parameters = context . MethodInfo . GetParameters ( ) ;
@@ -25,12 +40,10 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
2540
2641 var serviceProviderIsService = context . ApplicationServices . GetService < IServiceProviderIsService > ( ) ;
2742
28- var parameterCount = parameters . Length ;
29- var validatableParameters = new IValidatableInfo [ parameterCount ] ;
30- var parameterDisplayNames = new string [ parameterCount ] ;
31- var hasValidatableParameters = false ;
43+ // Use a list to only store validatable parameters instead of arrays for all parameters
44+ var validatableParameters = new System . Collections . Generic . List < ValidatableParameterEntry > ( ) ;
3245
33- for ( var i = 0 ; i < parameterCount ; i ++ )
46+ for ( var i = 0 ; i < parameters . Length ; i ++ )
3447 {
3548 // Ignore parameters that are resolved from the DI container.
3649 if ( IsServiceParameter ( parameters [ i ] , serviceProviderIsService ) )
@@ -40,13 +53,14 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
4053
4154 if ( options . TryGetValidatableParameterInfo ( parameters [ i ] , out var validatableParameter ) )
4255 {
43- validatableParameters [ i ] = validatableParameter ;
44- parameterDisplayNames [ i ] = GetDisplayName ( parameters [ i ] ) ;
45- hasValidatableParameters = true ;
56+ validatableParameters . Add ( new ValidatableParameterEntry (
57+ i ,
58+ validatableParameter ,
59+ GetDisplayName ( parameters [ i ] ) ) ) ;
4660 }
4761 }
4862
49- if ( ! hasValidatableParameters )
63+ if ( validatableParameters . Count == 0 )
5064 {
5165 return next ;
5266 }
@@ -55,18 +69,20 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
5569 {
5670 ValidateContext ? validateContext = null ;
5771
58- for ( var i = 0 ; i < context . Arguments . Count ; i ++ )
72+ foreach ( var entry in validatableParameters )
5973 {
60- var validatableParameter = validatableParameters [ i ] ;
61- var displayName = parameterDisplayNames [ i ] ;
74+ if ( entry . Index >= context . Arguments . Count )
75+ {
76+ continue ;
77+ }
6278
63- var argument = context . Arguments [ i ] ;
64- if ( argument is null || validatableParameter is null )
79+ var argument = context . Arguments [ entry . Index ] ;
80+ if ( argument is null )
6581 {
6682 continue ;
6783 }
6884
69- var validationContext = new ValidationContext ( argument , displayName , context . HttpContext . RequestServices , items : null ) ;
85+ var validationContext = new ValidationContext ( argument , entry . DisplayName , context . HttpContext . RequestServices , items : null ) ;
7086
7187 if ( validateContext == null )
7288 {
@@ -81,7 +97,7 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
8197 validateContext . ValidationContext = validationContext ;
8298 }
8399
84- await validatableParameter . ValidateAsync ( argument , validateContext , context . HttpContext . RequestAborted ) ;
100+ await entry . Parameter . ValidateAsync ( argument , validateContext , context . HttpContext . RequestAborted ) ;
85101 }
86102
87103 if ( validateContext is { ValidationErrors . Count : > 0 } )
0 commit comments