@@ -14,6 +14,9 @@ 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 record struct ValidatableParameterEntry ( int Index , IValidatableInfo Parameter , string DisplayName ) ;
19
+
17
20
public static EndpointFilterDelegate Create ( EndpointFilterFactoryContext context , EndpointFilterDelegate next )
18
21
{
19
22
var parameters = context . MethodInfo . GetParameters ( ) ;
@@ -25,12 +28,10 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
25
28
26
29
var serviceProviderIsService = context . ApplicationServices . GetService < IServiceProviderIsService > ( ) ;
27
30
28
- var parameterCount = parameters . Length ;
29
- var validatableParameters = new IValidatableInfo [ parameterCount ] ;
30
- var parameterDisplayNames = new string [ parameterCount ] ;
31
- var hasValidatableParameters = false ;
31
+ // Use a list to only store validatable parameters instead of arrays for all parameters
32
+ List < ValidatableParameterEntry > ? validatableParameters = null ;
32
33
33
- for ( var i = 0 ; i < parameterCount ; i ++ )
34
+ for ( var i = 0 ; i < parameters . Length ; i ++ )
34
35
{
35
36
// Ignore parameters that are resolved from the DI container.
36
37
if ( IsServiceParameter ( parameters [ i ] , serviceProviderIsService ) )
@@ -40,13 +41,15 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
40
41
41
42
if ( options . TryGetValidatableParameterInfo ( parameters [ i ] , out var validatableParameter ) )
42
43
{
43
- validatableParameters [ i ] = validatableParameter ;
44
- parameterDisplayNames [ i ] = GetDisplayName ( parameters [ i ] ) ;
45
- hasValidatableParameters = true ;
44
+ validatableParameters ??= [ ] ;
45
+ validatableParameters . Add ( new ValidatableParameterEntry (
46
+ i ,
47
+ validatableParameter ,
48
+ GetDisplayName ( parameters [ i ] ) ) ) ;
46
49
}
47
50
}
48
51
49
- if ( ! hasValidatableParameters )
52
+ if ( validatableParameters is null || validatableParameters . Count == 0 )
50
53
{
51
54
return next ;
52
55
}
@@ -55,18 +58,20 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
55
58
{
56
59
ValidateContext ? validateContext = null ;
57
60
58
- for ( var i = 0 ; i < context . Arguments . Count ; i ++ )
61
+ foreach ( var entry in validatableParameters )
59
62
{
60
- var validatableParameter = validatableParameters [ i ] ;
61
- var displayName = parameterDisplayNames [ i ] ;
63
+ if ( entry . Index >= context . Arguments . Count )
64
+ {
65
+ break ;
66
+ }
62
67
63
- var argument = context . Arguments [ i ] ;
64
- if ( argument is null || validatableParameter is null )
68
+ var argument = context . Arguments [ entry . Index ] ;
69
+ if ( argument is null )
65
70
{
66
71
continue ;
67
72
}
68
73
69
- var validationContext = new ValidationContext ( argument , displayName , context . HttpContext . RequestServices , items : null ) ;
74
+ var validationContext = new ValidationContext ( argument , entry . DisplayName , context . HttpContext . RequestServices , items : null ) ;
70
75
71
76
if ( validateContext == null )
72
77
{
@@ -81,7 +86,7 @@ public static EndpointFilterDelegate Create(EndpointFilterFactoryContext context
81
86
validateContext . ValidationContext = validationContext ;
82
87
}
83
88
84
- await validatableParameter . ValidateAsync ( argument , validateContext , context . HttpContext . RequestAborted ) ;
89
+ await entry . Parameter . ValidateAsync ( argument , validateContext , context . HttpContext . RequestAborted ) ;
85
90
}
86
91
87
92
if ( validateContext is { ValidationErrors . Count : > 0 } )
0 commit comments