ASP.NET Core Web API控制器重复初始化及状态重置问题咨询
问题:Web API每次CRUD后数据恢复默认,控制器每次调用都重新初始化
我是Web API开发新手,目前遇到一个问题:每次执行CRUD调用后,数据都会恢复到默认状态,并且每次调用前控制器对象都会重新初始化。希望有人能指导问题原因。
代码展示
Program.cs
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
PlayersController.cs
using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; using Unity_RestApi_Custom.Contracts; namespace Unity_RestApi_Custom.Controllers { [Route("api/[controller]")] public class PlayersController : Controller { int counter = 0; private static List<Player> players; public PlayersController(ILogger<PlayersController> logger) { //_logger = logger; players = new List<Player>(); players.Add(new Player(1, "Name 1 Text", 1)); players.Add(new Player(2, "Name 2 Text", 2)); players.Add(new Player(3, "Name 3 Text", 3)); System.Diagnostics.Debug.WriteLine("Testing Constructor"); } /* [HttpGet(Name = "Players")] public IEnumerable<Player> Get() { Player player = players.Single(p => p.Id == id); return Enumerable.Range(0, players.Count).Select(index => new Player { Id = players[index].Id , FullName = players[index].FullName, Score = players[index].Score }) .ToArray();; yield return player; }*/ [HttpGet] public JsonResult Get() { System.Diagnostics.Debug.WriteLine("Players Count == " + players.Count); return Json(players); //return new JsonResult(Random.Shared.Next()); } [HttpGet("{id}")] public JsonResult Get(int id) { Player player = players.Single(p => p.Id == id); return Json(player); } [HttpPost] public JsonResult Post([FromBody] Player newPlayer) { players.Add(newPlayer); return Json(players); } [HttpPut("{id}")] public JsonResult Put(int id,[FromBody] int newScore) { /*Player player = players.Single(player => player.Id == id); player.Score = newScore; return Json(player);*/ for (int i = 0; i < players.Count; i++) { if (players[i].Id == id) { players[i].Score = newScore; } } return Json(players); } [HttpDelete("{id}")] public JsonResult Delete(int id) { List<Player> playersLocal = players; Player player = playersLocal.Single(player => player.Id == id); playersLocal.Remove(player); players = playersLocal; //System.Diagnostics.Debug.WriteLine("Players Count == "+ playersLocal.Count); return Json(players); } } }
Player 模型类
using System; using Newtonsoft.Json; namespace Unity_RestApi_Custom.Contracts { [JsonObject,Serializable] public class Player { public int Id { get; set; } public string FullName { get; set; } public int Score { get; set; } public Player(int Id,string FullName,int Score) { this.Id = Id; this.FullName = FullName; this.Score= Score; } } }
问题原因分析
控制器生命周期特性:ASP.NET Core中,控制器默认是**瞬时(Transient)**生命周期,意味着每收到一个HTTP请求,都会创建一个全新的
PlayersController实例。这就是你看到“每次调用前控制器对象重新初始化”的原因。static变量被重复初始化:虽然你把
players声明为static,但在控制器的构造函数中,每次创建新控制器实例时都会执行players = new List<Player>()并添加默认数据,直接覆盖了之前通过CRUD操作修改的列表。这才是数据每次恢复默认的核心问题。
修复方案
方案1:修改static变量的初始化逻辑
把默认数据的初始化移到static变量声明处,或者只在players为空时才初始化,避免每次构造控制器都重置数据:
private static List<Player> players = new List<Player> { new Player(1, "Name 1 Text", 1), new Player(2, "Name 2 Text", 2), new Player(3, "Name 3 Text", 3) }; public PlayersController(ILogger<PlayersController> logger) { // 移除原来的初始化代码,只保留日志相关(如果需要) // _logger = logger; System.Diagnostics.Debug.WriteLine("Testing Constructor"); }
或者用惰性初始化:
private static List<Player> players; public PlayersController(ILogger<PlayersController> logger) { if (players == null) { players = new List<Player>(); players.Add(new Player(1, "Name 1 Text", 1)); players.Add(new Player(2, "Name 2 Text", 2)); players.Add(new Player(3, "Name 3 Text", 3)); } System.Diagnostics.Debug.WriteLine("Testing Constructor"); }
方案2:使用单例服务存储数据(更规范)
对于测试或小型应用,推荐创建一个单例服务来管理数据,替代控制器中的static变量:
- 创建数据服务接口和实现:
public interface IPlayerService { List<Player> GetAllPlayers(); Player GetPlayerById(int id); void AddPlayer(Player player); void UpdatePlayerScore(int id, int newScore); void DeletePlayer(int id); } public class PlayerService : IPlayerService { private List<Player> _players; public PlayerService() { _players = new List<Player> { new Player(1, "Name 1 Text", 1), new Player(2, "Name 2 Text", 2), new Player(3, "Name 3 Text", 3) }; } // 实现接口中的方法... public List<Player> GetAllPlayers() => _players; public Player GetPlayerById(int id) => _players.Single(p => p.Id == id); public void AddPlayer(Player player) => _players.Add(player); public void UpdatePlayerScore(int id, int newScore) { var player = _players.Single(p => p.Id == id); player.Score = newScore; } public void DeletePlayer(int id) { var player = _players.Single(p => p.Id == id); _players.Remove(player); } }
- 在Program.cs中注册单例服务:
builder.Services.AddSingleton<IPlayerService, PlayerService>();
- 修改控制器,通过依赖注入使用服务:
private readonly IPlayerService _playerService; public PlayersController(ILogger<PlayersController> logger, IPlayerService playerService) { // _logger = logger; _playerService = playerService; System.Diagnostics.Debug.WriteLine("Testing Constructor"); } [HttpGet] public JsonResult Get() { return Json(_playerService.GetAllPlayers()); } // 其他CRUD方法也改为调用_playerService的对应方法...
注意:以上两种方案都是基于内存存储,应用重启后数据会丢失。生产环境需要使用数据库(如SQL Server、SQLite等)来持久化数据。
内容的提问来源于stack exchange,提问作者Learners Tube
相关产品推荐
相关产品推荐

