C#中List<string>值未更新 WebAPI接口调用返回空列表问题
问题根因
ASP.NET Core 中 Controller 默认是瞬态生命周期:每次收到请求时,框架都会创建一个全新的 Controller 实例处理请求,请求处理完成后该实例就会被销毁回收。
你将存储数据的List<string>定义为 Controller 的实例字段,POST请求添加数据时,仅修改了当前请求对应的Controller实例内的集合;请求结束后这个实例被回收,添加的数据也随之丢失。后续发送GET查询请求时,框架又会创建全新的Controller实例,新实例的dataList是刚初始化的空集合,自然查询不到之前添加的内容。
可选解决方案
根据你的使用场景选对应方案即可:
方案1:静态集合(仅用于本地快速测试,不推荐生产使用)
将集合改为静态字段,静态字段归类型本身所有,不随Controller实例销毁而回收,所有请求共享同一份集合数据:
[Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { // 改为静态字段 private static readonly List<string> dataList = new List<string>(); // 多线程添加数据时加锁避免集合操作异常 private static readonly object _listLock = new object(); [HttpGet] public IActionResult GetData() { lock(_listLock){ return Ok(dataList.ToList()); } } [HttpPost] public IActionResult AddData() { var testData = new List<string>() { "ab", "cd", "efg" }; lock(_listLock){ dataList.AddRange(testData); } return Ok(); } }
注意:这种方案数据存在应用内存中,应用重启后数据会全部丢失,且多节点部署时不同节点的内存数据不互通,仅适合本地临时调试用。
方案2:单例存储服务(单节点部署推荐写法)
将数据存储逻辑从Controller中抽离,单独定义存储服务并注册为单例生命周期,所有请求注入同一个服务实例共享数据,符合依赖注入设计规范:
- 首先定义存储服务类:
public class TempDataStorage { private readonly List<string> _dataList = new(); private readonly object _lock = new(); public void AddData(IEnumerable<string> items) { lock (_lock) { _dataList.AddRange(items); } } public List<string> GetAll() { lock (_lock) { // 返回集合副本,避免外部直接修改内部存储 return _dataList.ToList(); } } }
- 在
Program.cs中注册单例服务:
var builder = WebApplication.CreateBuilder(args); // 注册单例存储服务 builder.Services.AddSingleton<TempDataStorage>(); // 其他原有服务注册逻辑 builder.Services.AddControllers(); var app = builder.Build(); // 其他中间件配置逻辑 app.MapControllers(); app.Run();
- 改造Controller,通过构造函数注入存储服务使用:
[Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { private readonly TempDataStorage _storage; public TestController(TempDataStorage storage) { _storage = storage; } [HttpGet] public IActionResult GetData() { return Ok(_storage.GetAll()); } [HttpPost] public IActionResult AddData() { var testData = new List<string>() { "ab", "cd", "efg" }; _storage.AddData(testData); return Ok(); } }
补充:你原有代码中接口方法标记了
async Task<IActionResult>但方法内没有任何await异步操作,可以直接去掉async关键字,避免不必要的状态机性能损耗。
方案3:持久化存储(生产环境推荐)
如果需要数据持久化不丢失、或者应用是多节点分布式部署,就不能把数据存在应用进程内存中,需要将数据存储到数据库、Redis等独立的持久化存储介质中,所有节点统一从存储介质读写数据。
内容的提问来源于stack exchange,提问作者IdleMan
相关产品推荐
相关产品推荐

