-
Notifications
You must be signed in to change notification settings - Fork 0
✨ Add and verify .NET 10 minimal API validation support with DataAnnotations #29
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
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
1d933b4
Initial plan
Copilot daf4879
Add .NET 10 minimal API validation tests for DataAnnotations
Copilot 4e27b1d
Simplify minimal API validation tests - use ValidationContext with se…
Copilot 0203f43
Add clarifying comments about IServiceProvider parameter in validatio…
Copilot adaabfa
Implement minimal API test with host builder - encountering circular …
Copilot 9387330
Add AddValidation() to reproduce circular reference issue with Option…
Copilot 9b09d0d
Add JsonIgnore attribute to Unspecified property in OptionalValue to …
desjoerd 4bd6fb3
Update version to 0.9 and remove obsolete comment about circular refe…
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
test/OptionalValues.DataAnnotations.Tests/MinimalApiValidationTest.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| using System.ComponentModel.DataAnnotations; | ||
| using System.Net; | ||
| using System.Net.Http.Json; | ||
|
|
||
| using Shouldly; | ||
|
|
||
| #if NET10_0_OR_GREATER | ||
| using Microsoft.AspNetCore.Builder; | ||
| using Microsoft.AspNetCore.Hosting; | ||
| using Microsoft.AspNetCore.Mvc.Testing; | ||
| using Microsoft.AspNetCore.TestHost; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Hosting; | ||
| #endif | ||
|
|
||
| namespace OptionalValues.DataAnnotations.Tests; | ||
|
|
||
| /// <summary> | ||
| /// Tests that verify OptionalValues DataAnnotations work with .NET 10's minimal API validation support. | ||
| /// In .NET 10, minimal APIs automatically validate models when AddValidation() is called. | ||
| /// See: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-10.0#validation-support-in-minimal-apis | ||
| /// | ||
| /// These tests create an actual minimal API with host builder and use AddValidation() to verify | ||
| /// that OptionalValues DataAnnotations work correctly with automatic validation. | ||
| /// </summary> | ||
| #if NET10_0_OR_GREATER | ||
| public class MinimalApiValidationTest : IAsyncLifetime | ||
| { | ||
| private WebApplication? _app; | ||
| private HttpClient? _client; | ||
|
|
||
| public class TestModel | ||
| { | ||
| [RequiredValue] | ||
| public OptionalValue<string> RequiredName { get; init; } | ||
|
|
||
| [OptionalRange(1, 100)] | ||
| public OptionalValue<int> RangeValue { get; init; } | ||
|
|
||
| [Specified] | ||
| public OptionalValue<string?> SpecifiedField { get; init; } | ||
| } | ||
|
|
||
| public async Task InitializeAsync() | ||
| { | ||
| // Create a minimal API host with AddValidation() | ||
| var builder = WebApplication.CreateBuilder(); | ||
|
|
||
| // Configure JSON options for OptionalValue support | ||
| builder.Services.ConfigureHttpJsonOptions(options => | ||
| { | ||
| options.SerializerOptions.AddOptionalValueSupport(); | ||
| }); | ||
|
|
||
| // Add validation support for minimal APIs in .NET 10 | ||
| builder.Services.AddValidation(); | ||
|
|
||
| // Use test server | ||
| builder.WebHost.UseTestServer(); | ||
|
|
||
| _app = builder.Build(); | ||
|
|
||
| // Create minimal API endpoint with automatic validation | ||
| _app.MapPost("/test", (TestModel model) => Results.Ok(model)) | ||
| .WithName("TestEndpoint"); | ||
|
|
||
| await _app.StartAsync(); | ||
| _client = _app.GetTestClient(); | ||
| } | ||
|
|
||
| public async Task DisposeAsync() | ||
| { | ||
| if (_app != null) | ||
| { | ||
| await _app.DisposeAsync(); | ||
| } | ||
| _client?.Dispose(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task ValidModel_ShouldPass_MinimalApiValidation() | ||
| { | ||
| // Arrange - Send valid JSON | ||
| var json = """{"RequiredName":"TestName","RangeValue":50,"SpecifiedField":"value"}"""; | ||
| var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"); | ||
|
|
||
| // Act - Post to minimal API which uses AddValidation() | ||
| var response = await _client!.PostAsync("/test", content); | ||
|
|
||
| // Assert | ||
| response.StatusCode.ShouldBe(HttpStatusCode.OK); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task InvalidModel_ShouldFail_MinimalApiValidation() | ||
| { | ||
| // Arrange - Send invalid JSON (out of range value) | ||
| var json = """{"RequiredName":"Test","RangeValue":150,"SpecifiedField":"value"}"""; | ||
| var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"); | ||
|
|
||
| // Act - Post to minimal API which uses AddValidation() | ||
| var response = await _client!.PostAsync("/test", content); | ||
|
|
||
| // Assert - Minimal API validation should return BadRequest | ||
| response.StatusCode.ShouldBe(HttpStatusCode.BadRequest); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task UnspecifiedOptionalFields_ShouldBeValid_MinimalApiValidation() | ||
| { | ||
| // Arrange - Don't send unspecified fields in JSON | ||
| var json = """{"RequiredName":"Test","SpecifiedField":null}"""; | ||
| var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"); | ||
|
|
||
| // Act - Post to minimal API which uses AddValidation() | ||
| var response = await _client!.PostAsync("/test", content); | ||
|
|
||
| // Assert | ||
| response.StatusCode.ShouldBe(HttpStatusCode.OK); | ||
| } | ||
| } | ||
| #else | ||
| public class MinimalApiValidationTest | ||
| { | ||
| [Fact] | ||
| public void MinimalApiValidation_OnlyAvailableInNet10() | ||
| { | ||
| // Minimal API validation with AddValidation() is only available in .NET 10+ | ||
| true.ShouldBeTrue(); | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.