TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #1035 1.42K
День восемьсот сорок шестой. #ЗаметкиНаПолях
Отмена Операции при Отмене HTTP Запроса
Я уже много раз писал про скоординированную отмену, например, здесь и здесь. И даже про улучшения, которые ожидаются в .NET6. Однако, я, к своему удивлению, упустил момент, что Kestrel может перехватывать событие отмены запроса со стороны пользователя, и передавать отмену операции методу действия контроллера.

Таким образом, можно просто передать CancellationToken в метод контроллера, который запускает длительную операцию:
public MyController {
public async Task<IActionResult>
DoSomethingAsync(CancellationToken token)
{
…
}
}

Entity Framework и ADO, а также, например, HttpClient, принимают токен отмены, и в случае отмены операции выбрасывают TaskCanceledException. В методе действия контроллера вы можете перехватить и обработать это исключение.

В своём коде вы можете использовать два способа:
- булево свойство IsCancellationRequested, которое вы можете проверять вручную в цикле или между вызовами длительных операций,
- метод ThrowIfCancellationRequested(), выбрасывающий исключение OperationCanceledException, которое вы впоследствии можете обработать.

Необработанные исключения в методах контроллера – это, конечно, плохая идея. Чтобы не засорять код контроллеров их обработкой, можно использовать фильтр исключений, например, такой:
public class OperationCanceledExceptionFilter : 
ExceptionFilterAttribute
{
public OperationCanceledExceptionFilter()
{}

public override void OnException(ExceptionContext context)
{
if(context.Exception is OperationCanceledException)
{
context.ExceptionHandled = true;
context.Result = new StatusCodeResult(400);
}
}
}

Обратите внимание, что мы перехватываем исключение OperationCanceledException. TaskCanceledException является его потомком, поэтому также будет перехвачено.

Также имейте в виду, что пользователь, отменивший запрос, конечно, не увидит никакого сообщения или кода ответа от сервера, поэтому какой именно код ответа будет использован, не играет роли, хотя формально существует код 499 Client Closed Request.

Стоит отметить ещё одну интересную особенность токена отмены. Swagger «понимает» смысл передачи его в метод действия контроллера, поэтому он не включает его в общедоступные параметры метода. Таким образом, в сгенерированной документации API у вас не будет лишних параметров конечных точек.

Конечно, токен отмены в методах действия контроллеров стоит добавлять с умом. Например, вы вряд ли хотите, чтобы транзакция по изменению сущности в базе поддерживала отмену посреди операции. Таким образом, наиболее безопасно использовать токен отмены в операциях без побочных эффектов, вроде получения данных от API.

Источники:
-
https://www.youtube.com/watch?v=b5dyPJ3zyRg
-
https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/
More from @netdeveloperdiary
  1. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  2. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  3. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  4. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  5. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  6. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →