在ASP.NET Core 6 API的ContentResultList中使用IAsyncEnumerable实现流式传输
可行,具体实现步骤如下
你可以直接将ContentResultList<T>中的Data属性类型从List<T>改为IAsyncEnumerable<T>,ASP.NET Core 6+的System.Text.Json序列化器原生支持流式序列化IAsyncEnumerable<T>,能实现数据的逐步传输。
1. 修改ContentResultList类
public class ContentResultList<T> { public bool IsSuccess { get; set; } public string Message { get; set; } // 将List<T>替换为IAsyncEnumerable<T> public IAsyncEnumerable<T> Data { get; set; } public int TotalPages { get; set; } = 0; public int CurrentPage { get; set; } = 1; // 修正原代码拼写错误:CurrrentPage → CurrentPage public int PageSize { get; set; } = 10; public int TotalNumberOfRecords { get; set; } = 0; public int RecordsTotal { get; set; } public int RecordsFiltered { get; set; } public T Result { get; set; } }
2. 调整API接口实现
在GET接口中,需要先获取分页元数据(总记录数、总页数等),再通过异步流式方式获取当前页数据。以EF Core为例:
[HttpGet] public async Task<ContentResultList<YourEntity>> GetItems(int page = 1, int pageSize = 10) { var query = _dbContext.YourEntities.AsQueryable(); // 先获取总记录数,用于计算分页元数据 var totalRecords = await query.CountAsync(); var totalPages = (int)Math.Ceiling(totalRecords / (double)pageSize); // 异步流式获取当前页数据 var data = query .Skip((page - 1) * pageSize) .Take(pageSize) .AsAsyncEnumerable(); // 转换为IAsyncEnumerable,避免一次性加载全部数据 return new ContentResultList<YourEntity> { IsSuccess = true, Message = "数据获取成功", Data = data, TotalPages = totalPages, CurrentPage = page, PageSize = pageSize, TotalNumberOfRecords = totalRecords, RecordsTotal = totalRecords, RecordsFiltered = totalRecords }; }
3. 关键注意事项
- 序列化逻辑:System.Text.Json会先序列化
ContentResultList<T>中的非流式属性(如IsSuccess、TotalPages等),再逐步序列化Data中的每一项,实现流式传输效果。 - 避免同步阻塞:确保数据来源支持异步流式获取(如EF Core的
AsAsyncEnumerable),不要将IAsyncEnumerable<T>转换回List<T>,否则会失去流式传输的意义。 - 客户端兼容性:现代HTTP客户端(HttpClient、浏览器Fetch API等)均支持接收流式JSON响应,无需额外适配。
内容的提问来源于stack exchange,提问作者Jalpesh Vadgama
相关产品推荐
相关产品推荐

