必须用 typedresults 替代 results,因其返回强类型 iresult 实现(如 ok),可被 .produces() 直接识别以生成准确 openapi 文档,支持单元测试直接断言属性,避免隐式转换和运行时错误;而 return new { } 或 string 仅固定返回 200 + text/plain 或 application/json,无法控制状态码与元数据。

Minimal API 中必须用 TypedResults 替代 Results,否则 OpenAPI 文档无法正确推导响应类型、单元测试难断言、运行时也容易因隐式转换出错。
为什么不能直接 return new { ... } 或 string?
直接返回 string 或匿名对象虽能跑通,但框架会按默认规则设 Content-Type(text/plain 或 application/json),且不带状态码语义和 OpenAPI 元数据。比如 app.MapGet("/ping", () => "ok") 永远是 200 + text/plain,想返回 204 或 404 就做不到。
-
string/Task<string></string>:强制 200 +text/plain,不可控 - 匿名类型 /
Task<t></t>(非IResult):强制 200 +application/json,无状态码选择 - 必须显式构造
IResult实例,而TypedResults提供的是强类型实现类(如Ok<user></user>),不是泛型接口
TypedResults.Ok 和 Results.Ok 的关键区别
TypedResults.Ok<user>()</user> 返回的是具体类型 Ok<user></user>,而 Results.Ok(new User()) 返回的是 IResult 接口——前者在编译期就锁定响应结构,后者到运行时才解析。
-
TypedResults.Ok<user>(user)</user>→ 类型为Ok<user></user>,可被.Produces<user>()</user>直接识别,Swagger 自动生成200: User定义 -
Results.Ok(user)→ 类型为IResult,需额外调用.Produces<user>()</user>才能补全文档,否则 Swagger 显示200: object - 单元测试中,
Ok<user></user>可直接 cast 并断言Value属性;IResult必须 await + ExecuteAsync + 模拟HttpContext才能测
常见 TypedResults 工厂方法及使用场景
优先选 TypedResults 下对应方法,避免混用 Results。所有方法名首字母大写,返回值类型即其名称(如 NotFound 返回 NotFound 类型)。
-
TypedResults.Ok<t>(value)</t>:成功返回资源,自动设 200 +application/json+ 正确 OpenAPI 响应体 -
TypedResults.Created<t>(string location, T value)</t>:POST 创建后返回 201,location填路径如$"/api/users/{id}" -
TypedResults.NoContent():204,适合 DELETE 或无返回体的更新操作 -
TypedResults.NotFound()或TypedResults.NotFound(string detail):404,不带 body 用前者,带提示用后者 -
TypedResults.BadRequest<t>(T error)</t>:400,传入错误模型(如ValidationFailure)
示例:app.MapGet("/users/{id}", (int id, IUserService svc) => { var u = svc.Get(id); return u is null ? TypedResults.NotFound() : TypedResults.Ok(u); });
Produces 和 WithName 必须配合 TypedResults 使用
TypedResults 自带类型信息,但 OpenAPI 文档生成仍需显式声明。漏掉 .Produces<t>()</t>,Swagger 就只显示 200: object;漏掉 .WithName("xxx"),接口在文档里就是 Get_123 这种随机名。
-
.Produces<user>()</user>要写在MapGet链式调用末尾,且泛型参数必须和TypedResults.Ok<user></user>一致 -
.WithName("Users_GetById")应紧接在路由定义后,用于 Swagger 标题和测试引用 - 若返回多种状态(如 200/404),需链式调用多次
.Produces<t>()</t>和.ProducesStatus(404)
复杂点在于:同一个端点若用 TypedResults.NotFound() 和 TypedResults.Ok<user>()</user> 分支返回,.Produces<user>()</user> 只覆盖 200 分支,404 分支还得加 .ProducesStatus(404) —— 这个细节常被忽略,导致文档缺失错误状态码定义。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











