Asp.net-Web-Api
ASP.NET Web Api 2.0 中哪個優先,ExceptionFilter 還是 ExceptionHandler?
我的 web api 2.0 中有一個全域 ExceptionHandler,它處理所有未處理的異常,以便向 api 呼叫者返回友好的錯誤消息。我還有一個全域 ExceptionFilter,它在我的 web api 中處理一個非常具體的異常並返回一個特定的響應。ExceptionFilter 是由外掛動態添加到我的 web api 中的,因此我無法在我的 ExceptionHandler 中執行它的操作。
我想知道我是否同時全域註冊了 ExceptionHandler 和 ExceptionFilter ,哪個將優先並首先執行?現在我可以看到 ExceptionFilter 在 ExceptionHandler 之前執行。而且我還可以在我的 ExceptionFilter 中看到,如果我創建一個響應,則 ExceptionHandler 沒有被執行。
可以安全地假設:
- ExceptionFilters 在 ExceptionHandlers 之前執行。
- 如果 ExceptionFilter 創建了響應,則 ExceptionHandler 將不會被執行。
我必須通過 System.Web.Http 進行調試才能找到我的問題的答案。所以答案是:
- 可以安全地假設 ExceptionFilters 將在 ExceptionHandlers 之前執行
- 如果 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。
我希望這是有用的!