Ответ
По умолчанию новый экземпляр контроллера создается для каждого HTTP-запроса, который соответствует его маршруту. Это обеспечивает изоляцию состояния между запросами и является рекомендуемой практикой.
Почему так? Это поведение (Transient lifetime) гарантирует, что поля контроллера не будут неявно использоваться для хранения данных между запросами, что предотвращает ошибки, связанные с параллелизмом.
Как это изменить? Вы можете зарегистрировать контроллер с другим временем жизни в DI-контейнере, но это требует осторожности.
// В Program.cs или Startup.ConfigureServices
// Scoped — один экземпляр на запрос (по умолчанию для контроллеров через AddControllers)
services.AddScoped<HomeController>();
// Singleton — один экземпляр на всё время работы приложения (ОПАСНО!)
// services.AddSingleton<HomeController>();
Ключевые моменты:
- Контроллеры должны быть stateless. Любые данные, сохраняемые между запросами, должны храниться во внешнем хранилище (база данных, кэш, сессия).
- Зависимости контроллера (сервисы) инжектируются через конструктор и разрешаются в соответствии со своим временем жизни (Transient, Scoped, Singleton).
- Регистрация контроллера как Singleton приведет к тому, что все его поля (и инжектированные Scoped-сервисы) будут общими для всех запросов, что вызовет race conditions и ошибки данных.