MichaelCleverly MichaelCleverly - 1 month ago 17
C# Question

Asynchronous error handling in MVC 5 filters

I've made a custom filter attribute extending the

HandleErrorAttribute
, that catches all exceptions.

My entire application is built around async architechture, throughout the stack.
This means, that I somehow have to use the
OnException(ExceptionContext contect)
override asynchronously. Something like this, would be how I imagined it (Simplified for readability):

public async override void OnException(ExceptionContext context)
{
base.OnException(context);
var logId = await LogException(e, httpContext); //LogException calls an async method and returns the ID of the exception, after it has been saved to the database. I this ID in the filterContext, which is why I need the result of the method
}


However, this would result in
InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle
.

I cannot simply call .Result on the task when called synchronously, as this would cause deadlocks.

So I guess my question is: How do I create a filter in MVC5, that can log errors asynchronously?

usr usr
Answer

Since error handling usually is not hot code there are no performance concerns here. Therefore, do what's most convenient to you.

For example, you can block on the task returned from LogException. There are multiple ways you can reliably avoid a deadlock. A simple way is Task.Run(() => LogException()).Wait();. This works because the task body runs without a synchronization context.

You also can add ConfigureAwait(false) inside of LogException but you cannot miss a single place. That makes this brittle.