This is a bug in ASP.NET Web API 2 and unfortunately, I don't think there's a workaround that will always succeed. We filed a bug to fix it on our side.
Ultimately, the problem is that we return a cancelled task to ASP.NET in this case, and ASP.NET treats a cancelled task like an unhandled exception (it logs the problem in the Application event log).
In the meantime, you could try something like the code below. It adds a top-level message handler that removes the content when the cancellation token fires. If the response has no content, the bug shouldn't be triggered. There's still a small possibility it could happen, because the client could disconnect right after the message handler checks the cancellation token but before the higher-level Web API code does the same check. But I think it will help in most cases.
David
config.MessageHandlers.Add(new CancelledTaskBugWorkaroundMessageHandler());
class CancelledTaskBugWorkaroundMessageHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
// Try to suppress response content when the cancellation token has fired; ASP.NET will log to the Application event log if there's content in this case.
if (cancellationToken.IsCancellationRequested)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
return response;
}
}