An unhandled exception causes the Web API service to crash when thrown in an asynchronous action
According to the documentation HttpResponseException
, web APIs are handled automatically and the web API should just return to the HttpResponseMessage
client with the appropriate one HttpStatusCode
, AND that works ... usually.
But if we throw out HttpResponseException
of the action marked async
, then it just doesn't work, it HttpResponseException
just crashes the whole service with something like "Exception was handled by user code" message. Adding a custom exclusion filter does not solve the problem because the web API does not detect the message HttpResponseException
.
Update 1
I researched further and found out that once you add a modifier await
to an action then any unhandled exception from that action will crash the web API service. And no ExceptionFilterAttributes are involved, the web API just doesn't execute them. You don't even need to throw an exception from truly asynchronous code, just add async
to the action so that all exceptions are completely unhandled.
It works fine here, the exception can be caught by some kind of exception filter:
public void Test()
{
throw new Exception("Hello");
}
And this causes the service to crash:
public async void Test()
{
throw new Exception("Hello");
}
Update 2
Well, it looks like everything works great if we change void
to some real type, here:
public async Task<int> Test()
{
throw new Exception("Hello");
}
So, it looks like an unhandled exception from async void
calling the service fails, but async Task<SomeType>
works well, exception filters capture everything except HttpResponseException
and HttpResponseException
are handled correctly by the web API.
Looks like I was just talking to myself, but would be interested to know why exceptions in actions async void
cannot be handled correctly?
source to share
One of the reasons why you should avoid async void
is the way you handle errors.
async void
are intended to be used as event handlers. All other methods async
must be async Task
or async Task<T>
. The analogue of the async
synchronous- void
rotation method is async Task
, not async void
.
async
methods that return a task object throw an exception on that task object. Methods async void
do not have a task object, so they handle exceptions by incrementing them by the SynchronizationContext
one that was active when the method was run async void
. This emulates the behavior of event handlers.
source to share