Asp.net-Web-Api

ASP.NET Web Api 2.0 中哪個優先,ExceptionFilter 還是 ExceptionHandler?

  • January 24, 2015

我的 web api 2.0 中有一個全域 ExceptionHandler,它處理所有未處理的異常,以便向 api 呼叫者返回友好的錯誤消息。我還有一個全域 ExceptionFilter,它在我的 web api 中處理一個非常具體的異常並返回一個特定的響應。ExceptionFilter 是由外掛動態添加到我的 web api 中的,因此我無法在我的 ExceptionHandler 中執行它的操作。

我想知道我是否同時全域註冊了 ExceptionHandler 和 ExceptionFilter ,哪個將優先並首先執行?現在我可以看到 ExceptionFilter 在 ExceptionHandler 之前執行。而且我還可以在我的 ExceptionFilter 中看到,如果我創建一個響應,則 ExceptionHandler 沒有被執行。

可以安全地假設:

  1. ExceptionFilters 在 ExceptionHandlers 之前執行。
  2. 如果 ExceptionFilter 創建了響應,則 ExceptionHandler 將不會被執行。

我必須通過 System.Web.Http 進行調試才能找到我的問題的答案。所以答案是:

  1. 可以安全地假設 ExceptionFilters 將在 ExceptionHandlers 之前執行
  2. 如果 ExceptionFilter 創建響應,則不會執行 ExceptionHandler。

為什麼會這樣:

當您註冊了一個 ExceptionFilter 以全域執行或為您的控制器操作執行時,所有 api 控制器繼承的 ApiController 基類會將結果包裝在 ExceptionFilterResult 中並呼叫其 ExecuteAsync 方法。這是 ApiController 中的程式碼,它執行以下操作:

if (exceptionFilters.Length > 0)
{
   IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices);
   IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices);
   result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler,
       result);
}

return result.ExecuteAsync(cancellationToken);

查看 ExceptionFilterResult.ExecuteAsync 方法:

try
{
   return await _innerResult.ExecuteAsync(cancellationToken);
}
catch (Exception e)
{
   exceptionInfo = ExceptionDispatchInfo.Capture(e);
}

// This code path only runs if the task is faulted with an exception
Exception exception = exceptionInfo.SourceException;
Debug.Assert(exception != null);

bool isCancellationException = exception is OperationCanceledException;

ExceptionContext exceptionContext = new ExceptionContext(
   exception,
   ExceptionCatchBlocks.IExceptionFilter,
   _context);

if (!isCancellationException)
{
   // We don't log cancellation exceptions because it doesn't represent an error.
   await _exceptionLogger.LogAsync(exceptionContext, cancellationToken);
}

HttpActionExecutedContext executedContext = new HttpActionExecutedContext(_context, exception);

// Note: exception filters need to be scheduled in the reverse order so that
// the more specific filter (e.g. Action) executes before the less specific ones (e.g. Global)
for (int i = _filters.Length - 1; i >= 0; i--)
{
   IExceptionFilter exceptionFilter = _filters[i];
   await exceptionFilter.ExecuteExceptionFilterAsync(executedContext, cancellationToken);
}

if (executedContext.Response == null && !isCancellationException)
{
   // We don't log cancellation exceptions because it doesn't represent an error.
   executedContext.Response = await _exceptionHandler.HandleAsync(exceptionContext, cancellationToken);
}

可以看到先執行了ExceptionLogger,然後執行了所有的ExceptionFilter,如果executeContext.Response == null,則執行ExceptionHandler。

我希望這是有用的!

引用自:https://stackoverflow.com/questions/28127042