Skip to content

Commit 287d892

Browse files
authored
Harden AddValidation check in validations generator (#61193)
* Harden AddValidation check in validations generator * Add test case
1 parent 8e14559 commit 287d892

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ internal bool FindAddValidation(SyntaxNode syntaxNode, CancellationToken cancell
2626
{
2727
var node = (InvocationExpressionSyntax)context.Node;
2828
var semanticModel = context.SemanticModel;
29+
var symbol = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol;
30+
if (symbol is not IMethodSymbol methodSymbol
31+
|| methodSymbol.ContainingType.Name != "ValidationServiceCollectionExtensions"
32+
|| methodSymbol.ContainingAssembly.Name != "Microsoft.AspNetCore.Http.Abstractions")
33+
{
34+
return null;
35+
}
2936
return semanticModel.GetInterceptableLocation(node, cancellationToken);
3037
}
3138
}

src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,70 @@ await VerifyEndpoint(compilation, "/complex-type", async (endpoint, serviceProvi
5151
});
5252
}
5353

54+
[Fact]
55+
public async Task DoesNotEmitIfNotCorrectAddValidationCallExists()
56+
{
57+
// Arrange
58+
var source = """
59+
using System;
60+
using System.ComponentModel.DataAnnotations;
61+
using System.Collections.Generic;
62+
using System.Threading.Tasks;
63+
using Microsoft.AspNetCore.Builder;
64+
using Microsoft.AspNetCore.Http;
65+
using Microsoft.AspNetCore.Http.Validation;
66+
using Microsoft.AspNetCore.Routing;
67+
using Microsoft.Extensions.DependencyInjection;
68+
69+
var builder = WebApplication.CreateBuilder();
70+
71+
builder.Services.AddValidation("example");
72+
SomeExtensions.AddValidation(builder.Services);
73+
74+
var app = builder.Build();
75+
76+
app.MapPost("/complex-type", (ComplexType complexType) => Results.Ok("Passed"));
77+
78+
app.Run();
79+
80+
public class ComplexType
81+
{
82+
[Range(10, 100)]
83+
public int IntegerWithRange { get; set; } = 10;
84+
}
85+
86+
public static class SomeExtensions
87+
{
88+
public static IServiceCollection AddValidation(this IServiceCollection services, string someString)
89+
{
90+
// This is not the correct AddValidation method
91+
return services;
92+
}
93+
94+
public static IServiceCollection AddValidation(this IServiceCollection services, Action<ValidationOptions>? configureOptions = null)
95+
{
96+
// This is not the correct AddValidation method
97+
return services;
98+
}
99+
}
100+
""";
101+
await Verify(source, out var compilation);
102+
// Verify that we don't validate types if no AddValidation call exists
103+
await VerifyEndpoint(compilation, "/complex-type", async (endpoint, serviceProvider) =>
104+
{
105+
var payload = """
106+
{
107+
"IntegerWithRange": 5
108+
}
109+
""";
110+
var context = CreateHttpContextWithPayload(payload, serviceProvider);
111+
112+
await endpoint.RequestDelegate(context);
113+
114+
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
115+
});
116+
}
117+
54118
[Fact]
55119
public async Task DoesNotEmitForExemptTypes()
56120
{

0 commit comments

Comments
 (0)