同步操作场景中的ExceptionFilter堆栈跟踪

时间:2016-05-04 22:20:22

标签: c# asynchronous asp.net-web-api asp.net-web-api2

我在Controller中有一个简单的同步动作,它会抛出一个异常,如下所示:

[RoutePrefix("")]
public class MyController : ApiController
{
    [Route("")]
    public HttpResponseMessage Get()
    {
        throw new Exception("whatever");
        return Request.CreateResponse(HttpStatusCode.OK, "response");
    }
}

我还有一个ExceptionFilterAttribute来获取应用程序中发生的异常

public class MyExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionContext)
    {
        var ex = actionContext.Exception;
        // Log ex, etc.
    }
}

一切正常,因为我确实在MyExceptionFilterAttribute中得到了例外。问题是堆栈跟踪。这是它的样子:

at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.ApiController.<InvokeActionWithExceptionFilters>d__1.MoveNext()"

所以我的问题是:如何获得“真正的”堆栈跟踪(这将指向控制器中发生异常的方法)?

更一般地说,因为显然有一些我不理解的东西,在这种情况下异步来自哪里? web api在遇到控制器方法时会自动创建异步任务吗?

我使用的是Web API v2.0(packages v5.0.0),无法升级到更新的版本(复杂的故事)。

更多信息:我遇到了this question所以我尝试从ActionFilterAttribute继承而不是ExceptionFilterAttribute,但是当ActionFilterAttribute被点击时,堆栈跟踪看起来就像上面那样。

1 个答案:

答案 0 :(得分:1)

如果您被迫不升级Web API包,那么您最好的选择可能是避免使用ActionFilters来处理异常。

更好(和全局)的方法是创建ExceptionHandler来替换Web API配置中的默认实现:

public class MyExceptionHandler : ExceptionHandler
{
    public override void Handle(ExceptionHandlerContext context)
    {
        var ex = context.Exception;

        //log exception, do stuff

        context.Result = new InternalServerErrorResult(context.Request);
    }

    public override bool ShouldHandle(ExceptionHandlerContext context)
    {
        bool shouldHandle;

        //logic to check if you should handle the exception or not

        return shouldHandle;
    }
}

WebApiConfig.cs内(假设config是您的HttpConfiguration对象):

config.Services.Replace(typeof(IExceptionHandler), new MyExceptionHandler());

如果您只想记录异常(而不是以某种方式处理它),那么您可以以类似的方式实现ExceptionLogger

public class MyExceptionLogger : ExceptionLogger
{
    public override void Log(ExceptionLoggerContext context)
    {
        MyLogger.Log(LogLevel.Error, context.Exception, "some message");
    }
}

再次:

config.Services.Replace(typeof(IExceptionLogger), new MyExceptionLogger());