Skip to content

Commit e052658

Browse files
committed
Add Trimming and NativeAoT tests for validation
1 parent 4c1b13e commit e052658

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.ComponentModel.DataAnnotations;
7+
using Microsoft.AspNetCore.Builder;
8+
using Microsoft.AspNetCore.Http;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Microsoft.Extensions.Validation;
11+
12+
var builder = WebApplication.CreateSlimBuilder();
13+
14+
builder.Services.AddValidation();
15+
16+
var app = builder.Build();
17+
18+
// Validation endpoints with different validatable types
19+
app.MapGet("/customers/{id}", ([Range(1, int.MaxValue)] int id) =>
20+
$"Getting customer with ID: {id}");
21+
22+
app.MapPost("/customers", (Customer customer) =>
23+
TypedResults.Created($"/customers/{customer.Id}", customer));
24+
25+
app.MapPost("/orders", (Order order) =>
26+
TypedResults.Created($"/orders/{order.OrderId}", order));
27+
28+
app.MapPost("/products", (Product product) =>
29+
TypedResults.Ok(new ProductResponse("Product created", product)));
30+
31+
app.MapPut("/addresses/{id}", (int id, Address address) =>
32+
TypedResults.Ok(new AddressResponse($"Address {id} updated", address)));
33+
34+
app.MapPost("/users", (User user) =>
35+
TypedResults.Created($"/users/{user.Id}", user));
36+
37+
app.MapPost("/inventory", ([EvenNumber] int productId, [Required] string name) =>
38+
TypedResults.Ok(new InventoryResponse(productId, name)));
39+
40+
// Endpoint with disabled validation
41+
app.MapPost("/products/bulk", (Product[] products) =>
42+
TypedResults.Ok(new BulkProductResponse("Bulk products created", products.Length)))
43+
.DisableValidation();
44+
45+
app.Run();
46+
47+
return 100;
48+
49+
public class Customer
50+
{
51+
[Required]
52+
[Range(1, int.MaxValue)]
53+
public int Id { get; set; }
54+
55+
[Required]
56+
[StringLength(100, MinimumLength = 2)]
57+
public string Name { get; set; } = string.Empty;
58+
59+
[EmailAddress]
60+
public string Email { get; set; } = string.Empty;
61+
62+
[Range(18, 120)]
63+
[Display(Name = "Customer Age")]
64+
public int Age { get; set; }
65+
66+
// Complex property with nested validation
67+
public Address Address { get; set; } = new();
68+
}
69+
70+
public record Product(
71+
[Required] string Name,
72+
[Range(0.01, double.MaxValue)] decimal Price,
73+
[StringLength(500)] string Description = ""
74+
)
75+
{
76+
[Required]
77+
public string Category { get; set; } = string.Empty;
78+
}
79+
80+
public class Address
81+
{
82+
[Required]
83+
[StringLength(200)]
84+
public string Street { get; set; } = string.Empty;
85+
86+
[Required]
87+
[StringLength(100)]
88+
public string City { get; set; } = string.Empty;
89+
90+
[Required]
91+
[RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid ZIP code format")]
92+
public string ZipCode { get; set; } = string.Empty;
93+
94+
[StringLength(2, MinimumLength = 2)]
95+
public string State { get; set; } = string.Empty;
96+
}
97+
98+
public class Order : IValidatableObject
99+
{
100+
[Required]
101+
public string OrderId { get; set; } = string.Empty;
102+
103+
[Required]
104+
public int CustomerId { get; set; }
105+
106+
[Range(0.01, double.MaxValue)]
107+
public decimal Total { get; set; }
108+
109+
public DateTime OrderDate { get; set; } = DateTime.Now;
110+
111+
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
112+
{
113+
if (OrderDate > DateTime.Now.AddDays(1))
114+
{
115+
yield return new ValidationResult(
116+
"Order date cannot be more than 1 day in the future.",
117+
new[] { nameof(OrderDate) });
118+
}
119+
120+
if (Total > 10000 && CustomerId == 0)
121+
{
122+
yield return new ValidationResult(
123+
"High-value orders require a valid customer ID.",
124+
new[] { nameof(CustomerId), nameof(Total) });
125+
}
126+
}
127+
}
128+
129+
public record User(
130+
[Required] [StringLength(50)] string Username,
131+
[EmailAddress] string Email,
132+
[Phone] string PhoneNumber = ""
133+
)
134+
{
135+
[Required]
136+
[Range(1, int.MaxValue)]
137+
public int Id { get; set; }
138+
139+
[StringLength(100)]
140+
public string DisplayName => $"{Username} ({Email})";
141+
142+
[CreditCard]
143+
public string CreditCardNumber { get; set; }
144+
}
145+
146+
// Custom validation attribute
147+
public class EvenNumberAttribute : ValidationAttribute
148+
{
149+
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
150+
{
151+
if (value is int number && number % 2 != 0)
152+
{
153+
return new ValidationResult("The number must be even.", new[] { validationContext.MemberName });
154+
}
155+
156+
return ValidationResult.Success;
157+
}
158+
}
159+
160+
public record ProductResponse(string Message, Product Product);
161+
162+
public record AddressResponse(string Message, Address Address);
163+
164+
public record InventoryResponse(int ProductId, string Name);
165+
166+
public record BulkProductResponse(string Message, int Count);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<ItemGroup>
4+
<TestConsoleAppSourceFiles Include="BasicMinimalApiWithValidation.cs">
5+
<EnabledProperties>EnableRequestDelegateGenerator</EnabledProperties>
6+
</TestConsoleAppSourceFiles>
7+
</ItemGroup>
8+
9+
</Project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<ItemGroup>
4+
<TestConsoleAppSourceFiles Include="../Microsoft.Extensions.Validation.NativeAotTests/BasicMinimalApiWithValidation.cs">
5+
<EnabledProperties>EnableRequestDelegateGenerator</EnabledProperties>
6+
</TestConsoleAppSourceFiles>
7+
</ItemGroup>
8+
9+
</Project>

0 commit comments

Comments
 (0)