You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 10 Minimal API+SwaggerUI处理GET复杂数据遇400错误

.NET 10 Minimal API GET请求返回400错误排查

问题详情

基于.NET 10搭建的Minimal API,使用SwaggerUI测试GET接口时,Swagger能正确展示输入类型,但发送请求始终返回HTTP 400错误。

核心代码

Input类:

public class Input 
{
    public string? StringVal { get; set; } = "";
    public string[] ArrayVals { get; set; } = [];
    public InputMore? More { get; set; }

    public static bool TryParse(string? json, out Input input) 
    {
        input = new Input();
        return true;
    }
}

InputMore类:

public class InputMore
{
    public string? StringVal { get; set; }
    public string[] ArrayVals { get; set; } = [];

    public static bool TryParse(string? json, out InputMore input)
    {
        input = new InputMore();
        return true;
    }
}

端点定义:

public class DummyEndpoints 
{
    public DummyEndpoints (WebApplication app) 
    {
        app.MapGet("/getTest", this.GetTest);
    }

    private IResult GetTest(HttpContext context, [AsParameters] Input input) 
    {
        Console.WriteLine(input.StringVal);
        Console.WriteLine(input.ArrayVals.Length);
        return Results.Ok("Get Test");
    }
}

SwaggerUI展示的输入示例

{
    "stringVal": "string",
    "arrayVals": [
        "string"
    ]
}

更新补充:API启动配置

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

IServiceCollection services = builder.Services;

services.AddOpenApi();

WebApplication app = builder.Build();

_ = new DummyEndpoints(app);

app.MapOpenApi();

app.UseSwaggerUI((SwaggerUIOptions options) => {
    options.SwaggerEndpoint("/openapi/v1.json", "Nothing v1");
});

调试尝试

将Input类中的单个对象属性改为数组后,情况有所改善:

public class Input 
{
    public string? StringVal { get; set; } = "";
    public string[] ArrayVals { get; set; } = [];
    public InputMore? MoreOne { get; set; }
    public InputMore[]? MoreMany { get; set; }

    public static bool TryParse(string? json, out Input input) 
    {
        input = new Input();
        return true;
    }
}

查看/openapi/v1.json发现:直接使用单个对象时,Swagger将其类型错误识别为string;改用数组时,类型识别正常。


问题原因与解决方案

原因分析

  1. 自定义TryParse方法干扰模型绑定:为Input和InputMore定义的TryParse(string, out T)方法,会让ASP.NET Core认为该类型支持从字符串解析。结合[AsParameters]特性时,框架会尝试把查询参数值当作字符串解析成Input对象,而非按照复杂对象绑定逻辑处理,导致绑定失败返回400。
  2. GET请求参数绑定逻辑冲突:[AsParameters]默认从查询字符串绑定参数,但SwaggerUI展示的是JSON请求体格式,GET请求使用请求体传参不符合HTTP规范,且框架默认对GET请求的请求体绑定支持有限,进一步加剧绑定失败。

解决方案

  1. 移除自定义TryParse方法:删除Input和InputMore中的TryParse静态方法,让框架使用默认的复杂对象绑定逻辑。移除后,Swagger会正确识别对象类型,不再标记为string。
  2. 调整GET请求参数传递方式:
    • 若坚持用GET,将复杂对象拆分为查询参数,示例格式:/getTest?StringVal=test&ArrayVals=val1&ArrayVals=val2&More.StringVal=subTest
    • 更规范的做法是改为POST请求,用[FromBody]接收JSON体,符合HTTP语义且绑定更顺畅:
      // 修改端点定义
      app.MapPost("/postTest", this.PostTest);
      
      private IResult PostTest([FromBody] Input input) 
      {
          Console.WriteLine(input.StringVal);
          Console.WriteLine(input.ArrayVals.Length);
          return Results.Ok("Post Test");
      }
      
  3. 若必须用GET请求体传参(不推荐):显式启用GET请求的请求体绑定支持:
    // 启动配置中添加
    builder.Services.Configure<MvcOptions>(options =>
    {
        options.AllowEmptyInputInBodyModelBinding = true;
    });
    // 端点方法中使用[FromBody]
    private IResult GetTest([FromBody] Input input) 
    {
        // ...业务逻辑
    }
    

内容的提问来源于stack exchange,提问作者TheLovelySausage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 00:05:15