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.
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());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.