diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs index fbf7673b19fd..1cb8061204ee 100644 --- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs +++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs @@ -26,6 +26,13 @@ internal bool FindAddValidation(SyntaxNode syntaxNode, CancellationToken cancell { var node = (InvocationExpressionSyntax)context.Node; var semanticModel = context.SemanticModel; + var symbol = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol; + if (symbol is not IMethodSymbol methodSymbol + || methodSymbol.ContainingType.Name != "ValidationServiceCollectionExtensions" + || methodSymbol.ContainingAssembly.Name != "Microsoft.AspNetCore.Http.Abstractions") + { + return null; + } return semanticModel.GetInterceptableLocation(node, cancellationToken); } } diff --git a/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs b/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs index 4249a7455bf0..410c74a5cecc 100644 --- a/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs +++ b/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs @@ -51,6 +51,70 @@ await VerifyEndpoint(compilation, "/complex-type", async (endpoint, serviceProvi }); } + [Fact] + public async Task DoesNotEmitIfNotCorrectAddValidationCallExists() + { + // Arrange + var source = """ +using System; +using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Validation; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +var builder = WebApplication.CreateBuilder(); + +builder.Services.AddValidation("example"); +SomeExtensions.AddValidation(builder.Services); + +var app = builder.Build(); + +app.MapPost("/complex-type", (ComplexType complexType) => Results.Ok("Passed")); + +app.Run(); + +public class ComplexType +{ + [Range(10, 100)] + public int IntegerWithRange { get; set; } = 10; +} + +public static class SomeExtensions +{ + public static IServiceCollection AddValidation(this IServiceCollection services, string someString) + { + // This is not the correct AddValidation method + return services; + } + + public static IServiceCollection AddValidation(this IServiceCollection services, Action? configureOptions = null) + { + // This is not the correct AddValidation method + return services; + } +} +"""; + await Verify(source, out var compilation); + // Verify that we don't validate types if no AddValidation call exists + await VerifyEndpoint(compilation, "/complex-type", async (endpoint, serviceProvider) => + { + var payload = """ + { + "IntegerWithRange": 5 + } + """; + var context = CreateHttpContextWithPayload(payload, serviceProvider); + + await endpoint.RequestDelegate(context); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + }); + } + [Fact] public async Task DoesNotEmitForExemptTypes() {