ExceptionFilter stack trace in synchronous action scenario

本小妞迷上赌 提交于 2019-12-08 04:31:28

问题


I have a simple synchronous action in a Controller that throws an exception like so :

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

I also have an ExceptionFilterAttribute to get a hold of exceptions that occur in the application

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

Everything works fine in that I do get a hold of the exception in MyExceptionFilterAttribute. The problem is the stack trace. Here is what it looks like :

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()"

So my question : How do I get the "real" stack trace (that would point to the method in the controller where the exception occured) ?

More generally, because clearly there is something I don't understand, where is the async coming from in this scenario ? Does the web api automatically create an async task when it hits a controller method ?

I am using Web API v2.0 (packages v5.0.0) and cannot upgrade to more recent versions (complicated story).

More info : I ran into this question so I tried inheriting from ActionFilterAttribute instead of ExceptionFilterAttribute but the stack trace already looked like the above one when the ActionFilterAttribute was getting hit.


回答1:


If you are forced to not upgrade Web API packages, then you best option is probably to avoid using ActionFilters for handling exceptions at all.

A better (and global) approach would be to create an ExceptionHandler to replace the default implementation inside the Web API configuration:

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;
    }
}

And inside WebApiConfig.cs (assuming config is your HttpConfiguration object):

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

If you, instead, only want to log the exception (and not handling it in some way), then you could implement an ExceptionLogger in a similar way:

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

And again:

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


来源:https://stackoverflow.com/questions/37039046/exceptionfilter-stack-trace-in-synchronous-action-scenario

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!