@@ -14,6 +14,21 @@ namespace Microsoft.AspNetCore.Http.Validation;
14
14
15
15
internal static class ValidationEndpointFilterFactory
16
16
{
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
+
17
32
public static EndpointFilterDelegate Create ( EndpointFilterFactoryContext context , EndpointFilterDelegate next )
18
33
{
19
34
var parameters = context . MethodInfo . GetParameters ( ) ;
@@ -25,12 +40,10 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
25
40
26
41
var serviceProviderIsService = context . ApplicationServices . GetService < IServiceProviderIsService > ( ) ;
27
42
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 > ( ) ;
32
45
33
- for ( var i = 0 ; i < parameterCount ; i ++ )
46
+ for ( var i = 0 ; i < parameters . Length ; i ++ )
34
47
{
35
48
// Ignore parameters that are resolved from the DI container.
36
49
if ( IsServiceParameter ( parameters [ i ] , serviceProviderIsService ) )
@@ -40,13 +53,14 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
40
53
41
54
if ( options . TryGetValidatableParameterInfo ( parameters [ i ] , out var validatableParameter ) )
42
55
{
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 ] ) ) ) ;
46
60
}
47
61
}
48
62
49
- if ( ! hasValidatableParameters )
63
+ if ( validatableParameters . Count == 0 )
50
64
{
51
65
return next ;
52
66
}
@@ -55,18 +69,20 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
55
69
{
56
70
ValidateContext ? validateContext = null ;
57
71
58
- for ( var i = 0 ; i < context . Arguments . Count ; i ++ )
72
+ foreach ( var entry in validatableParameters )
59
73
{
60
- var validatableParameter = validatableParameters [ i ] ;
61
- var displayName = parameterDisplayNames [ i ] ;
74
+ if ( entry . Index >= context . Arguments . Count )
75
+ {
76
+ continue ;
77
+ }
62
78
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 )
65
81
{
66
82
continue ;
67
83
}
68
84
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 ) ;
70
86
71
87
if ( validateContext == null )
72
88
{
@@ -81,7 +97,7 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
81
97
validateContext . ValidationContext = validationContext ;
82
98
}
83
99
84
- await validatableParameter . ValidateAsync ( argument , validateContext , context . HttpContext . RequestAborted ) ;
100
+ await entry . Parameter . ValidateAsync ( argument , validateContext , context . HttpContext . RequestAborted ) ;
85
101
}
86
102
87
103
if ( validateContext is { ValidationErrors . Count : > 0 } )
0 commit comments