Woody1193
Woody1193

Reputation: 7960

API exception filter returns 200 response code on exception in ASP.NET MVC

I wrote an exception filter for my API to handle exceptions throw in the API:

using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ApiExceptionFilter : ExceptionFilterAttribute {

    public override void OnException(ExceptionContext context) {

        // First, generate the status code based on the exception type
        HttpStatusCode status = context.Exception switch {
            UnauthorizedAccessException => HttpStatusCode.Unauthorized,
            ArgumentException => HttpStatusCode.BadRequest,
            MissingHeaderException => HttpStatusCode.BadRequest,
            NotFoundException => HttpStatusCode.NotFound,
            _ => HttpStatusCode.InternalServerError,
        };

        // Next, inject the status code and exception message into
        // a new error response and set the result with it
        context.Result = new JsonResult(new ErrorResponse {
            StatusCode = status,
            Message = context.Exception.Message
        });

        // Finally, call the base function
        base.OnException(context);
    }
}

This function intercepts exceptions as expected but the problem I'm having is that it always returns an OK response. How do I ensure that the response includes the exception message and that the response code is a non-200 value?

Upvotes: 3

Views: 2941

Answers (2)

shukebeta
shukebeta

Reputation: 101

on .NET Core/.NET 6, we don't have ExceptionResult, but we can still achieve this goal. We can manually set the StatusCode for this request.

    public override void OnException(ExceptionContext actionExecutedContext)
    {
        _logger.Error(actionExecutedContext.Exception);
        actionExecutedContext.ExceptionHandled = true;
        actionExecutedContext.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
        actionExecutedContext.Result = new ObjectResult(new ErrorResponse()
        {
            StatusCode = (HttpStatusCode) StatusCodes.Status500InternalServerError,
            Message = actionExecutedContext.Exception.Message,
        });
        base.OnException(actionExecutedContext);
    }

Upvotes: 2

John Glenn
John Glenn

Reputation: 1629

Instead of returning a JsonResult - which does not expose a status code property to be set - return an ExceptionResult and set the status code like so:

context.Result = new ExceptionResult(context.Exception, true)
{ StatusCode = status };

If you still want to use your ErrorResponse object, just use an object result:

context.Result = new ObjectResult(new ErrorResponse {
    StatusCode = status,
    Message = context.Exception.Message
    })
    // set status code on result
    { StatusCode = status };

Upvotes: 5

Related Questions