Mil*_*hev 19 asp.net-web-api asp.net-web-api2 asp.net-web-api-filters
我的web api 2.0中有一个全局ExceptionHandler,它处理所有未处理的异常,以便向api调用者返回一个友好的错误消息.我还有一个全局ExceptionFilter,它在我的web api中处理一个非常特殊的异常并返回一个特定的响应.ExceptionFilter是由插件动态添加到我的web api所以我无法在我的ExceptionHandler中做它做的事情.
我想知道我是否全局注册了ExceptionHandler和ExceptionFilter,哪一个优先并先执行?现在我可以看到ExceptionFilter正在ExceptionHandler之前执行.而且我也可以在我的ExceptionFilter中看到,如果我创建了一个响应,则不会执行ExceptionHandler.
可以安全地假设:
ExceptionFilters在ExceptionHandlers之前执行.
如果ExceptionFilter创建响应,则不会执行ExceptionHandler.
Mil*_*hev 30
我不得不通过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);
Run Code Online (Sandbox Code Playgroud)
查看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);
}
Run Code Online (Sandbox Code Playgroud)
您可以看到首先执行ExceptionLogger,然后执行所有ExceptionFilters,然后如果executionContext.Response == null,则执行ExceptionHandler.
我希望这很有用!
| 归档时间: |
|
| 查看次数: |
3341 次 |
| 最近记录: |