Skip to content

Commit 85f8764

Browse files
Copilotcaptainsafia
andcommitted
Optimize array allocations in ValidationEndpointFilterFactory
Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
1 parent b9460c8 commit 85f8764

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

src/Http/Routing/src/ValidationEndpointFilterFactory.cs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ namespace Microsoft.AspNetCore.Http.Validation;
1414

1515
internal 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

Comments
 (0)