Wednesday, 13 February 2019

Exception Handling In Web API


Exceptions are the errors that occurs at runtime while application execution. Exception handling is the process of handling this type of exceptions in the code. We can handle these exceptions in various ways which are as follows:
   1. Using HttpResponseException
   2. Using CreateErrorResponse
   3. Using Exception Filter
   4. Using Exception Handler


Using HttpResponseException
Using this class we can return HTTP Status code by specifying it in its constructor. For example, we can return “Not Found” HTTP Status code in case of no record found in database for any requested data. HttpResponseException’s constructor also accepts HttpResponseMessage so we can also return response message using this class. 


[HttpGet]
public int GetItemByID(int itemID)
{
   var itemObj = context.Items.Where(item => item.Id == itemID).FirstOrDefault();
   if (itemObj== null)
   {
       throw new HttpResponseException(HttpStatusCode.NotFound);
   }
   return item;
}

Using CreateErrorResponse
Using Request.CreateErrorReponse() method we can return some meaningful error message to the user with HTTP Status code. Since CreateErrorResponse() return HttpResponseMessage so the return type of action method should be HttpResponseMessage.

[HttpGet]
public HttpResponseMessage GetItemByID(int itemID)
{
var itemObj = context.Items.Where(item => item.Id == itemID).FirstOrDefault();
if (itemObj == null)
{
string message = "No item found with ID " + itemID;
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
return Request.CreateResponse(HttpStatusCode.OK, itemObj); ;
}

Using Exception Filters
Exception filters are used to handle unhandled exception that is originated from controller actions. Whenever an unhandled exception is occurred in controller action, this filter executes and handle it. We can create our custom exception filter by implementing ExceptionFilterAttribute class and overriding its OnException methodWe can apply exception filter by decorating the action method or controller with it. We can also apply this globally by registering it in WebApiConfig.cs file. Let’s take an example.
  
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;

namespace WebAPIPractice.Filters
{
    public class CustomExceptionFilter : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            string exceptionMessage = string.Empty;
            if (actionExecutedContext.Exception.InnerException == null)
            {
                exceptionMessage = actionExecutedContext.Exception.Message;
            }
            else
            {
                exceptionMessage = actionExecutedContext.Exception.InnerException.Message;
            }
            HttpResponseMessage response = new HttpResponseMessage()
            {
                Content = new StringContent("An unhandled exception has occured."),
                StatusCode = HttpStatusCode.InternalServerError
            };
            actionExecutedContext.Response = response;
        }

    }
}

Apply Exception Filter on Controller
   [CustomExceptionFilter]
  public class HomeController : Controller
  {      
    ....
    ....
  }

Apply Exception Filter on Action
 [CustomExceptionFilter]
 public IHttpActionResult Index()
 {
    ....
    ....
 } 

 Apply Exception Filter globally

namespace WebAPIPractice
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Filters.Add(new CustomExceptionFilter());
           ....
           ....
        }
    }
}
  
Using Exception Handlers
There are some cases when Exception filters fails to handle exception which are as follows:
   1. Error inside the exception filter.
   2. Exception related to routing.
   3. Error inside the Message Handlers class.
   4. Error in Controller Constructor.

We can handle such cases globally using ExceptionHandler class. Following is the code to implement our Custom Global Exception Handler.

using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.ExceptionHandling;
using System.Web.Http.Results;

namespace ecommerceWebApi.Providers
{
    public class GlobalExceptionHandleProvider : ExceptionHandler
    {
        public override async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
        {
            await Task.Run(() =>
            {
                const string errorMessage = "An unexprected error occured";
                var response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, errorMessage);
                response.Headers.Add("X-Error", errorMessage);
                context.Result = new ResponseMessageResult(response);
            });
        }
    }
}

As we register Exception filter in WebApiConfig.cs file, similarly we have to register our Exception Handler too.

namespace WebAPIPractice
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Filters.Add(new CustomExceptionFilter());
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandleProvider());
           ....
           ....
        }
    }
}

I hope you find this post helpful. Please comment about this post and provide any suggestion for further posts.

Thanks

1 comment: