Code to demonstrate the problem:
- Assume Test Thing is an real implementation, such as DB invocation.
- The documentation for Web API states that unhanded exceptions will be caught in a global handler allowing you to process them.
- If I replace MyErrorHandler with an ExceptionFilter this does indeed work, except the code base I'm working with uses handlers because the error logic is a cross cutting concern and will be the same regardless of where the error came from.
- If the type of exception thrown is not a TaskCancelledException this invokes the handler as expected.
- I've tried the latest version of Web API too (5.2.3).
- The only work around is to add a try/catch block around everywhere that can throw this type of exception, needless to say this is painful and something I wish to avoid hence the use of the handler.
I hate to call this a bug given this is not my code, but after hours of attempts it's starting to feel that way.
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.ExceptionHandling;
namespace WebApplication3.Controllers
{
public class TestController : ApiController
{
public async Task<string> Get()
{
var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1));
return await new TestThing().ExecuteAsync(cancellationTokenSource.Token);
}
}
public class MyErrorHandler : ExceptionHandler
{
public override Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
public class TestThing
{
public async Task<string> ExecuteAsync(CancellationToken cancellationToken)
{
// Remove this to see the problem, I don't want to add these
// try/catch statements all over the codebase.
try
{
await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
}
catch (Exception ex)
{
throw new Exception("Failure...");
}
return await Task.FromResult("Testing...");
}
}
}