Читаем Язык программирования C#9 и платформа .NET5 полностью

В отличие от большинства фильтров в ASP.NET Core, которые имеют обработчик событий "перед" и "после", фильтры исключений располагают только одним обработчиком: OnException (или OnExceptionAsync). Обработчик принимает один параметр, ExceptionContext, который предоставляет доступ к ActionContext, а также к сгенерированному исключению.

Кроме того, фильтры принимают участие во внедрении зависимостей, позволяя получить доступ в коде к любому элементу внутри контейнера. В рассматриваемом примере вам необходим экземпляр реализации IWebHostEnvironment, внедренный в фильтр, который будет использоваться для выяснения среды времени выполнения. Если средой является Development, тогда ответ должен также включать трассировку стека. Добавьте переменную уровня класса для хранения экземпляра реализации IWebHostEnvironment и конструктор:

private readonly IWebHostEnvironment _hostEnvironment;

public CustomExceptionFilterAttribute(IWebHostEnvironment hostEnvironment)

{

  _hostEnvironment = hostEnvironment;

}

Код в обработчике OnException проверяет тип сгенерированного исключения и строит соответствующий ответ. В случае среды Development в сообщение ответа включается трассировка стека. Затем создается динамический объект, который содержит значения для отправки вызывающему запросу, и возвращается в IActionResult. Вот модифицированный код метода:

public override void OnException(ExceptionContext context)

{

  var ex = context.Exception;

   string stackTrace = _hostEnvironment.IsDevelopment

     ? context.Exception.StackTrace : string.Empty;

  string message = ex.Message;

  string error;

    IActionResult actionResult;

  switch (ex)

  {

    case DbUpdateConcurrencyException ce:

      // Возвращается код HTTP 400.

      error = "Concurrency Issue.";

      actionResult = new BadRequestObjectResult(

        new {Error = error, Message = message, StackTrace = stackTrace});

      break;

    default:

      error = "General Error.";

      actionResult = new ObjectResult(

        new {Error = error, Message = message, StackTrace = stackTrace})

      {

        StatusCode = 500

      };

      break;

  }

  //context.ExceptionHandled = true; // Если убрать здесь комментарий,

                                     // то исключение поглощается

  context.Result = actionResult;

}

Если вы хотите, чтобы фильтр исключений поглотил исключение и установил код состояния в 200 (скажем, для регистрации ошибки в журнале, не возвращая ее клиенту), тогда поместите следующую строку перед установкой Result (в предыдущем примере кода просто уберите комментарий):

context.ExceptionHandled = true;

<p id="AutBody_Root1431"><strong>Добавление фильтров в конвейер обработки</strong></p>

Фильтры можно применять к методам действий, контроллерам или глобально к приложению. Код "перед" фильтров выполняется снаружи вовнутрь (глобальный, контроллер, метод действия), в то время как код "после" фильтров выполняется изнутри наружу (метод действия, контроллер, глобальный).

На уровне приложения фильтры добавляются в методе ConfigureServices класса Startup. Откройте файл класса Startup.cs и поместите в начало файла следующий оператор using:

using AutoLot.Api.Filters;

Модифицируйте метод AddControllers, добавив специальный фильтр:

services

  .AddControllers(config => config.Filters.Add(

      new CustomExceptionFilterAttribute(_env)))

  .AddJsonOptions(options =>

  {

    options.JsonSerializerOptions.PropertyNamingPolicy = null;

    options.JsonSerializerOptions.WriteIndented = true;

  })

  .ConfigureApiBehaviorOptions(options =>

  {

  ...

  });

<p id="AutBody_Root1432"><strong>Тестирование фильтра исключений</strong></p>

Чтобы протестировать фильтр исключений, откройте файл WeatherForecastController.cs и обновите метод действия Get показанным ниже кодом:

[HttpGet]

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT