C# ASP.NET Core Web API返回空对象数组:数据存在却无法正常输出
问题分析与解决方法
核心问题1:值元组的JSON序列化缺陷
你返回的List<(string listName, DateTime timeCreated)>是值元组列表,ASP.NET Core默认的System.Text.Json序列化器无法识别值元组的命名语法糖——运行时值元组的实际字段为Item1、Item2,且这些字段属于内部私有类型,序列化器无法读取,最终输出空对象{}。
核心问题2:HttpGet使用[FromBody]不符合HTTP规范
HttpGet请求的设计逻辑是通过URL传递参数,而非请求体。虽然部分客户端支持GET带请求体,但这违反HTTP标准,可能引发兼容性问题(如部分代理、网关会丢弃GET请求体)。
解决方案
1. 替换值元组为强类型DTO(推荐)
创建专门的DTO类承载返回数据,序列化器可正确识别属性名:
// 定义DTO类 public class ListInfoDto { public string ListName { get; set; } public DateTime TimeCreated { get; set; } }
修改服务层方法的返回类型与逻辑:
public async Task<List<ListInfoDto>> LoadAllLists(string targetUserId) { using (var connection = new SqlConnection(_configuration.GetConnectionString("DefaultConnection"))) { connection.Open(); using (var command = new SqlCommand("SELECT listName, timeCreated FROM [dbo].[jsonList] WHERE userid = @userid", connection)) { command.Parameters.AddWithValue("@userid", targetUserId); using (var reader = await command.ExecuteReaderAsync()) { var responseList = new List<ListInfoDto>(); while (await reader.ReadAsync()) { responseList.Add(new ListInfoDto { ListName = reader.GetString(0), TimeCreated = reader.GetDateTime(1) }); } return responseList; } } } }
2. 修正HttpGet的参数传递方式
将userId改为URL查询参数或路由参数:
方式一:查询参数
[HttpGet("getAllLists")] public async Task<IActionResult> LoadAllLists([FromQuery] string userId) { var lists = await _listDataHandlingService.LoadAllLists(userId); return Ok(lists); }
请求URL示例:/api/RequestHandling/getAllLists?userId=xxx
方式二:路由参数
[HttpGet("getAllLists/{userId}")] public async Task<IActionResult> LoadAllLists(string userId) { var lists = await _listDataHandlingService.LoadAllLists(userId); return Ok(lists); }
请求URL示例:/api/RequestHandling/getAllLists/xxx
旧项目能正常工作的原因
大概率旧项目使用了Newtonsoft.Json(Json.NET)作为序列化器,Json.NET对值元组的命名元素有特殊处理,可将其序列化为对应命名属性;而当前项目默认使用System.Text.Json,无此特性。若坚持使用值元组,可切换回Newtonsoft.Json,但仍推荐使用DTO,代码可读性与可维护性更强。
内容的提问来源于stack exchange,提问作者pKr
相关产品推荐
相关产品推荐

