-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Hi Asp.net team,
I've been a big proponent of using unhandled exception handlers in our asp.net web services. However, the more we looked at it in detail, the less the strategy works. This applies both to the "classic" asp.net error handlers enabled via UseExceptionHandler() and the modern one based on the IExceptionHandler interface.
We use custom error handlers for several things:
- To return an error status code and error payload to the caller
- To close some request-specific objects, i.e. issue some custom error metrics and logs
We've been aware that if an exception happens after the response has started (i.e. while writing to the output stream) the custom exception handlers are not invoked. However, recently we discovered a new confusing case - in a percentage of the requests (but not all), when the caller of the service drops the connection (i.e. HttpContext.RequestAborted is signaled) the exception handler is also not invoked.
These cases make it very hard to write a consistent error handling strategy based on the built-in error handling mechanisms. We can write error handling code that takes into consideration whether the response has already started. However, these error cases leave a significant number of failed requests outside of the default error handling, and they must be handled somehow.
I decided to remove the error handlers and wrap the top-level middleware in a custom middleware that catches and handles all exceptions from the inner middlewares and controllers, whether the response has started or not, whether the caller dropped the connection or not, and processes them the same way as the former custom error handler did. This works just fine, but it leads to the obvious question - what's the "right" thing to do?
Strangely, the asp.net runtime's unhandled exception handler is invoked every time an exception makes it through, regardless of request status, it's just the custom handlers that are skipped.
What does the Asp.Net team recommend? I need an exception handler that is guaranteed to be executed regardless of when the exception happens. I can continue to use my custom top-level middleware, but the very existence of the error handling documented mechanisms gives a misleading picture to developers. This issue has caused us to undercount errors, and it's unclear for how long. If the RequestAborted case had caused the error handler to be skipped 100%, we would have identified the issue right away, but because only some requests end up in this corner case we did not identify it until much later.
Thanks
F.
Expected Behavior
No response
Steps To Reproduce
- Service A accepts calls from a variety of clients
- Service A calls service B asynchronously (using standard HttpClient APIs)
- The call to service B has a guarded timeout that involves the request cancellation token HttpContext.RequestAborted
- Caller drops connection for whatever reason, at any time
- If request to B is in progress at the time, it is correctly aborted and a TaskCanceledException is rethrown
- Service A expects this exception to be caught by its unhandled exception handler where final logging/metrics are issued
- Exception handler is not invoked. We validated this in various ways, even placed an "entered exception handler" log line as the first code in the error handler.
Exceptions (if any)
No response
.NET Version
.Net 8.0
Anything else?
No response