After many experiments with different exception handling approaches I ended up using middleware. It worked the best for my ASP.NET Core Web API application. It handles application exceptions as well as exceptions from filters and I have full control over exception handling and creating a response json.
Here is my exception handling middleware:
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context /* other scoped dependencies */)
{
try
{
await next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var code = HttpStatusCode.InternalServerError; // 500 if unexpected
if (exception is MyNotFoundException)
code = HttpStatusCode.NotFound;
else if (exception is MyUnauthorizedException)
code = HttpStatusCode.Unauthorized;
else if (exception is MyException)
code = HttpStatusCode.BadRequest;
var result = JsonConvert.SerializeObject(new { error = exception.Message });
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code; return context.Response.WriteAsync(result);
}
}
Register it before MVC in Startup class:
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseMvc();
Here is an example of exception response:
{ "error": "Authentication token is not valid." }
You can add stack trace, exception type name, error codes or anything you want to it. Very flexible. Hope it's a good starting point for you!.