R. Campos
R. Campos

Reputation: 957

HttpError is ignored when creating an error response in a custom ExceptionFilterAttribute (if the exception is throwed in another attribute)

I have received the assignment to make our C# Webapi return always error responses with the following format:

{
    "error": {
        "code": 15,
        "message": "My custom error message"
    }
}

Because of that I registered my own ExceptionFilterAttribute:

 public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
    {

        class CustomError
        {
                public int code { get; set; }
                public String message { get; set; }
        }

 public override void OnException(HttpActionExecutedContext context)
            {

                if (context.Exception is BaseException)
                {
                    BaseException exception = (BaseException)context.Exception;
                    HttpError error = new HttpError();
                    CustomError customError = new CustomError
                    {
                        code=exception.CustomError.code,
                        message=exception.CustomError.message
                    };
                    error.Add("error", customError);
                    context.Response = context.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, error);
                }
                else
                {
                    context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
                }
            }

This is working very well when the exception was throwed in a controller. But if the exception was throwed in an attribute (AuthorizeAttribute or EnableQueryAttribute), althoug my custom ExceptionFilter is called and the same code is executed, the response generated ignores the given HttpError and the response has the following body:

  {
    "error": {
        "code": "",
        "message": ""
    }
}

I'm not very skilled in c#, I'm pretty sure that I'm doing something wrong, but I don't know what :S

Thanks in advance.

Edit 1:

I'm applying the Attribute that throws the exception at each method where the attribute is needed. For example I have an Odata Controller for an entity called "event":

 [CustomAuthentication]
    [CustomEnableQueryAttribute(PageSize = 20)]
    public IQueryable<Event> Get()
    {
        (...)
        return result;
    }

As said, if the exception is throwed in the body of the controller, then my CustomExceptionFilter is invoked, and the custom response is created correctly.

But if the exception is thrown in the CustomAuthenticationAttribute or in the CustomEnableQueryAttribute, then altough my CustomExceptionFilter is invoked and the very same code is executed, the body response is wrong (see example).

Upvotes: 0

Views: 294

Answers (1)

Pranay Rana
Pranay Rana

Reputation: 176886

Filter are mean for only controller but for global errors you need to use Global Error Filter in WebAPI.

to handle error thrown from attribute you need to Create Global Error Hnandler : https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling

class OopsExceptionHandler : ExceptionHandler
{
    public override void HandleCore(ExceptionHandlerContext context)
    {
        context.Result = new TextPlainErrorResult//you have to create this class
        {
            Request = context.ExceptionContext.Request,
            Content = "Oops! Sorry! Something went wrong." +
                      "Please contact [email protected] so we can try to fix it."
        };
    }
}

there are a number of cases that exception filters can't handle. For example:

  1. Exceptions thrown from controller constructors.
  2. Exceptions thrown from message handlers.
  3. Exceptions thrown during routing.
  4. Exceptions thrown during response content serialization .

Upvotes: 1

Related Questions