.NET 10 Minimal API验证在DTO包含JsonElement成员时抛出“Property 'this[]' not found on type 'JsonElement'”
在.NET 10(SDK 10.0.300)上,启用Minimal API验证管道并使用 AddValidation() 时,当请求的DTO包含一个 System.Text.Json.JsonElement 成员时,会在请求阶段抛出一个 InvalidOperationException。请求永远不会到达端点。
最小重现:
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddValidation();
var app = builder.Build();
app.MapPost("/test", (MyRequest request) => Results.Ok());
app.Run();
public class MyRequest
{
[Required]
[MaxLength(10)]
public string Name { get; set; } = default!;
public JsonElement Payload { get; set; }
}
.csproj 文件:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
请求:
POST /test
Content-Type: application/json
{ "name": "test", "payload": { "foo": "bar" } }
结果 — HTTP 500,完整异常和堆栈跟踪:
System.InvalidOperationException: Property 'this[]' not found on type 'JsonElement'.
at Microsoft.Extensions.Validation.ValidatablePropertyInfo.ValidateAsync(Object value, ValidateContext context, CancellationToken cancellationToken)
at Microsoft.Extensions.Validation.ValidatableTypeInfo.ValidateMembersAsync(Object value, ValidateContext context, CancellationToken cancellationToken)
at Microsoft.Extensions.Validation.ValidatableTypeInfo.ValidateAsync(Object value, ValidateContext context, CancellationToken cancellationToken)
at Microsoft.Extensions.Validation.ValidatablePropertyInfo.ValidateAsync(Object value, ValidateContext context, CancellationToken cancellationToken)
at Microsoft.Extensions.Validation.ValidatableTypeInfo.ValidateMembersAsync(Object value, ValidateContext context, CancellationToken cancellationToken)
at Microsoft.Extensions.Validation.ValidatableTypeInfo.ValidateAsync(Object value, ValidateContext context, CancellationToken cancellationToken)
at Microsoft.Extensions.Validation.ValidatableParameterInfo.ValidateAsync(Object value, ValidateContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Http.Validation.ValidationEndpointFilterFactory.<>c__DisplayClass1_0.d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Http.RequestDelegateFactory.g__ExecuteAwaited|130_0(ValueTask1 valueTask, HttpContext httpContext, JsonTypeInfo1 jsonTypeInfo)
at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass102_2.d.MoveNext()
观察要点:
- 管道会像将
ValidatableTypeInfo.ValidateMembersAsync视作可验证模型一样递归进入JsonElement,并在解析它所命名的成员this[]时失败 - 它在生成验证结果之前就崩溃了,因此一个真正违反
[MaxLength(10)]的请求也会返回500,而不是返回400 - 移除
JsonElement成员,或不调用AddValidation(),可以避免崩溃
关于 JsonElement 的设计:
Payload故意是一个不透明的JSON文档——它的形状由运行时的JSON架构定义,而不是由固定的C#类型决定,因此不适用POCO(重点在于接受并对任意文档进行模式验证)。JsonElement是保存任意JSON的典型System.Text.Json类型,这也是它被放在DTO中的原因。
这个问题不是关于是否应该以不同的方式建模——而是验证管道在 JsonElement 上崩溃,而不是跳过或优雅地报错。
问题:在DTO包含 JsonElement 时,这是否是.NET 10验证管道的已知限制/错误?是否有受支持的方式在验证遍历中排除特定成员(或类型)?
解决方案
这似乎是一个已知问题——请参阅 Validations in minimal APIs fails on several types from System.Text.Json @github,根据 fix @github 的链接,这个问题应该会在即将发布的版本中得到修复。
现在你可以尝试通过使用另一种类型来修复它,例如 JsonNode:
public class MyRequest
{
[Required]
[MaxLength(10)]
public string Name { get; set; } = default!;
public JsonNode Payload { get; set; }
}
对我来说有效(在10.0.201和 10.0.300上测试通过):

