为何WebApi的ApiController对象会为每个请求实例化?求相关文档依据
ASP.NET Web API中ApiController每个请求实例化的设计缘由与文档参考
没错,你和团队观察到的这个现象完全正确——ASP.NET Web API(包括后续的ASP.NET Core Web API)默认会为每个传入请求创建一个全新的ApiController实例。我当初刚接触Web API时也误以为控制器是单例复用的,毕竟很多后端服务类都是单例模式,所以这个设计确实容易让人产生误解。
为什么要采用“每个请求一个实例”的设计?
这里的核心考量主要集中在三个方面:
- 线程安全保障:Web API是无状态的服务,请求处理是并发进行的。如果控制器是单例,所有请求会共享控制器的实例字段、属性,很容易出现多个请求同时修改同一数据的线程安全问题。每次创建新实例从根源上避免了这类并发风险,开发者不用额外编写复杂的线程同步逻辑。
- 依赖注入的兼容性:控制器通常会依赖各种服务,比如数据库上下文(DbContext)这类作用域生命周期的服务,或者一些瞬时创建的工具类。如果控制器是单例,就无法直接注入这些生命周期更短的服务(DI系统不允许单例依赖作用域/瞬时服务,会引发生命周期不匹配的问题)。每个请求创建新控制器实例,就能完美适配DI的各种生命周期规则,轻松注入所需的服务。
- 请求状态隔离:每个请求对应独立的控制器实例,意味着每个请求的临时状态(比如请求参数的临时处理结果、中间变量)都被隔离在自己的实例中,不会和其他请求互相干扰。请求处理完成后,控制器实例会被回收,相关状态自然释放,减少了内存泄漏或状态污染的可能性。
官方文档参考
官方文档里明确说明了这个设计规则:
默认情况下,Web API框架为每个HTTP请求创建一个控制器的新实例。当控制器实现
IDisposable接口时,框架会在请求结束时调用Dispose方法。
在ASP.NET Core中,控制器的生命周期被定义为作用域(Scoped),这和ASP.NET Core的DI系统保持一致——作用域服务会在每个请求范围内创建一次,控制器作为作用域服务自然遵循这个生命周期规则。
如果你们想尝试修改这个行为(非常不推荐),可以通过自定义控制器激活器来实现,但官方强烈警告这种做法会引入线程安全、DI生命周期冲突等一系列潜在问题,除非有特殊的业务场景,否则不建议这么做。
内容的提问来源于stack exchange,提问作者E-Riz
相关产品推荐
相关产品推荐

