Search code examples
c#asp.netasp.net-web-apiexceptionhandler

How to use customexceptionhandlers in ASP.net web-api


I am trying to understand custom exceptionhandlers but am not getting the hang of it. I tried implementing a custom exception handler like explained in the following pages:
https://www.exceptionnotfound.net/the-asp-net-web-api-exception-handling-pipeline-a-guided-tour/ https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/web-api-global-error-handling

Now my code is:

public class CustomRestErrorHandlerException : ExceptionHandler
{
    public void CustomError(String error)
    {
        var message = new HttpResponseMessage(HttpStatusCode.NoContent)
        {
            Content = new StringContent("An unknown error occurred saying" + error)
        };

        throw new HttpResponseException(message);
    }

    public override void Handle(ExceptionHandlerContext context)
    {
        if (context.Exception is ArgumentNullException)
        {
            var result = new HttpResponseMessage(HttpStatusCode.BadRequest)
            {
                Content = new StringContent(context.Exception.Message),
                ReasonPhrase = "ArgumentNullException"
            };

            context.Result = new ErrorMessageResult(context.Request, result);
        }
        else if (context.Exception is ArgumentException)
        {
            var result = new HttpResponseMessage(HttpStatusCode.NoContent)
            {
                Content = new StringContent(context.Exception.Message),
                ReasonPhrase = "Argument is not found"
            };

            context.Result = new ErrorMessageResult(context.Request, result);
        }
        else if (context.Exception is ArgumentOutOfRangeException)
        {
            var result = new HttpResponseMessage(HttpStatusCode.NotImplemented)
            {
                Content = new StringContent(context.Exception.Message),
                ReasonPhrase = "Argument is out of range"
            };

            context.Result = new ErrorMessageResult(context.Request, result);

        }
        else
        {
            CustomError(context.Exception.Message);
        }
    }

    public class ErrorMessageResult : IHttpActionResult
    {
        private HttpRequestMessage _request;
        private HttpResponseMessage _httpResponseMessage;

        public ErrorMessageResult(HttpRequestMessage request, HttpResponseMessage httpResponseMessage)
        {
            _request = request;
            _httpResponseMessage = httpResponseMessage;
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(_httpResponseMessage);
        }
    }
}

Then I try to call the exceptionhandler which I obviously do wrong : (this I probably do not understand <<

    [Route("api/***/***")]
    [HttpGet]
    public IHttpActionResult Clear****()
    {
        try
        {
            // try clearing
        }
        catch(Exception e)
        {
            throw new CustomRestErrorHandlerException();     << error occurs here 
        }

        return this.Ok();
    }

As you can see the error occurs because the exception is not an exceptionhandler but I have no idea how to then throw an exception through an custom exception handler since it's explained nowhere.

Can anyone explain this to me with a small example perhaps?


Solution

  • ExceptionHandler's have to be registered in the Web API configuration. This can be done in the WebApiConfig.cs file as shown below, where config is of type System.Web.Http.HttpConfiguration.

    config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
    

    Once they are registered they are automatically called during unhandled exceptions. To test it out you might want to throw an exception in the action method such as:

    [Route("api/***/***")]
    [HttpGet]
    public IHttpActionResult Clear****()
    {
        try
        {
            // try clearing
        }
        catch(Exception e)
        {
            throw new ArgumentNullException();     << error occurs here 
        }
    
        return this.Ok();
    }
    

    You can now put a breakpoint in your exception handler and see how the unhandled exception is caught by the global ExceptionHandler.