I am developing WebAPI and want to catch all my ApiException custom exceptions and display WebAPI-friendly responses. The ApiException exception can be thrown from Action or Filter like IAuthorizationFilter or ActionFilterAttribute.
First I tried to use IExceptionFilter but later I found that the IExceptionFilter handles only exceptions thrown from Actions and not from other Filters.
public class ApiExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
var exception = context.Exception;
if (exception is not ApiException responseException)
{
responseException = new ApiException(ResponseMessageType.UnhandledException);
}
context.Result = new ObjectResult(new ResultMessageDto(responseException))
{
StatusCode = responseException.HttpStatusCode
};
}
}
The second approach that I found many suggest to use is the Middleware but this is not the correct way by WebAPI design.
public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;
public ErrorHandlerMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception exception)
{
var response = context.Response;
response.ContentType = "application/json";
if (exception is not ApiException responseException)
{
responseException = new ApiException(ResponseMessageType.UnhandledException);
}
response.StatusCode = responseException.HttpStatusCode;
await response.WriteAsJsonAsync(new ResultMessageDto(responseException), new JsonSerializerOptions()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = null
});
}
}
}
The Middleware exception handling skips WebAPI MVC OutputFormaters and responds only in JSON or what is set by the developer. This solution is bad by design because do not respect Accept header.
How to handle Exceptions in Actions and Filters without leaving MVC scope?