Skip to content

Implement runtime-based IValidatableTypeInfoResolver for minimal API validation #62497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jun 27, 2025

This PR implements a runtime implementation of IValidatableTypeInfoResolver to enable minimal-API validation when the source-generator path is unavailable (e.g., dynamic compilation, IDEs without generators, or environments where generators are turned off).

Background

Previously, the validation system had:

  • Compile-time story: Microsoft.AspNetCore.Http.ValidationsGenerator source-generator for AOT-friendly static lookups
  • Runtime parameter discovery: RuntimeValidatableParameterInfoResolver for method parameters
  • Runtime type discovery: TryGetValidatableTypeInfo was a stub that always returned false

This left a gap where validation wouldn't work in dynamic scenarios without the generator.

Implementation

Core Components

RuntimeValidatableTypeInfoResolver - Main resolver class that:

  • Uses reflection to walk public instance properties recursively
  • Builds ValidatableTypeInfo graphs that mirror compile-time generator output
  • Handles validation attributes like [Required], [Range], [Display], etc.

Cycle Prevention & Performance:

  • HashSet<Type> tracking during discovery prevents infinite recursion (A ↔ B references)
  • ConcurrentDictionary<Type, IValidatableInfo?> for thread-safe caching
  • Skips primitives, enums, strings, DateTime (same logic as parameter resolver)

Registration:

  • Added to ValidationOptions.Resolvers in AddValidation()
  • Placed after parameter resolver but before user-added fallbacks
  • Generated resolvers still take precedence when available

Example Usage

// Works without source generators now!
public class Person
{
    [Required]
    [StringLength(50)]
    public string Name { get; set; } = string.Empty;

    [Range(0, 120)]
    public int Age { get; set; }

    public Address Address { get; set; } = new();
}

public class Address  
{
    [Required]
    public string City { get; set; } = string.Empty;
}

// Validation now works at runtime
services.AddValidation();
// Validates nested objects, collections, handles cycles automatically

Testing

  • 11 unit tests covering primitives, complex types, collections, cycles, caching
  • 4 integration tests verifying service registration and resolver ordering
  • Manual verification with real POCOs and validation scenarios

All tests pass and validate the expected behavior matches the original issue requirements.

Fixes #61220.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copy link
Contributor

Greetings human! You've submitted a PR that modifies code that is shared with https://github.com/dotnet/runtime . Please make sure you synchronize this code with the changes in that repo!

Copilot AI and others added 3 commits June 27, 2025 23:18
Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
…tion

Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Implement runtime-based IValidatableTypeInfoResolver implementation Implement runtime-based IValidatableTypeInfoResolver for minimal API validation Jun 27, 2025
@Copilot Copilot AI requested a review from captainsafia June 27, 2025 23:31
Copilot finished work on behalf of captainsafia June 27, 2025 23:31
@captainsafia
Copy link
Member

@copilot Update the RuntimeValidatableTypeInfoResolverTests tests to use the validatable info types returned by cases that support them to validate actual test data.

…t data

Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jun 28, 2025

@copilot Update the RuntimeValidatableTypeInfoResolverTests tests to use the validatable info types returned by cases that support them to validate actual test data.

Updated the RuntimeValidatableTypeInfoResolverTests to use the returned validatable info objects to validate actual test data. The tests now verify validation behavior with both valid and invalid data scenarios, ensuring the runtime resolver works correctly in practice. Commit ee9c087

Copilot finished work on behalf of captainsafia June 28, 2025 00:12
@captainsafia captainsafia marked this pull request as ready for review June 30, 2025 16:56
Copy link
Contributor

Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime.
To make sure no conflicting changes have occurred, please rerun validation before merging. You can do this by leaving an /azp run comment here (requires commit rights), or by simply closing and reopening.

@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Jul 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Attention: Shared Code Modified pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement runtime-based IValidatableTypeInfoResolver implementation
2 participants