Какой жизненный цикл у контроллера в ASP.NET Core?

«Какой жизненный цикл у контроллера в ASP.NET Core?» — вопрос из категории ASP.NET Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Контроллеры в ASP.NET Core по умолчанию имеют жизненный цикл Scoped (с областью действия), что означает создание нового экземпляра для каждого HTTP-запроса. Это обеспечивает изоляцию и безопасность данных между запросами.

Последовательность этапов для одного запроса:

  1. Разрешение зависимостей: DI-контейнер создает экземпляр контроллера, разрешая все зависимости, указанные в его конструкторе (например, сервисы, логгеры).
  2. Выполнение фильтров: Выполняются различные фильтры (авторизации, ресурсов, действий, исключений, результатов) в определенном порядке.
  3. Вызов метода действия (Action Method): Вызывается соответствующий запросу метод контроллера, который выполняет бизнес-логику и возвращает IActionResult.
  4. Выполнение результата: Фреймворк выполняет возвращенный результат (рендерит View, возвращает JSON и т.д.).
  5. Освобождение ресурсов: Если контроллер реализует интерфейс IDisposable или IAsyncDisposable, вызывается соответствующий метод Dispose для очистки неуправляемых ресурсов. После этого экземпляр контроллера готов к сборке мусора.
public class OrderController : Controller, IDisposable
{
    private readonly IOrderService _orderService;
    private readonly ILogger<OrderController> _logger;
    private bool _disposed = false;

    // 1. DI-контейнер инжектирует зависимости при создании
    public OrderController(IOrderService orderService, ILogger<OrderController> logger)
    {
        _orderService = orderService;
        _logger = logger;
    }

    // 3. Вызов метода действия
    public IActionResult Get(int id)
    {
        var order = _orderService.GetOrder(id);
        return Ok(order); // 4. Выполнение результата
    }

    // 5. Освобождение ресурсов (вызывается фреймворком)
    public void Dispose()
    {
        if (!_disposed)
        {
            _logger.LogTrace("OrderController disposed.");
            // Освобождение неуправляемых ресурсов, если они есть
            _disposed = true;
        }
    }
}

Важно: Не храните состояние (данные) в полях контроллера, которое должно сохраняться между запросами, так как для нового запроса будет создан новый экземпляр.