How to handle errors in ASP.Net Web API

Learn to handle runtime errors using exceptions and return appropriate error codes and error messages in ASP.Net Web API

banana peel slip accident mistake fall by rapideye getty
RapidEye / Getty

Microsoft’s ASP.Net Web API is a lightweight framework you can use to build stateless RESTful services that run on HTTP. Exceptions are errors that occur at runtime, and exception handling is the technique of handling runtime errors in your application code.

Every ASP.Net Web API developer should know how to handle exceptions in Web API and how to send out appropriate error codes and error messages from Web API controller methods. We will examine how to perform these tasks in the sections below. 

Using HttpResponseException in ASP.Net Web API

You can use the HttpResponseException class to return specific HTTP status codes and messages from your controller methods in Web API. Here is an example.

public Employee GetEmployee(int id)
{
    Employee emp = employeeRepository.Get(id);
    if (emp == null)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent("Employee doesn't exist", System.Text.Encoding.UTF8, "text/plain"),
            StatusCode = HttpStatusCode.NotFound
        }
        throw new HttpResponseException(response);
    }
    return emp;
}

If your Web API returns IHttpActionResult, you might want to write the GetEmployee method as shown below.

public IHttpActionResult GetEmployee(int id)
{
    Employee emp = employeeRepository.Get(id);
    if (emp == null)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent("Employee doesn't exist", System.Text.Encoding.UTF8, "text/plain"),
            StatusCode = HttpStatusCode.NotFound
        }
        throw new HttpResponseException(response);
    }
    return Ok(emp);
}

Note that the error code and error message are assigned to the response object, and that an instance of HttpResponseException is returned when an exception occurs in the action method of the Web API controller.

Using HttpError in ASP.Net Web API

You can use the CreateErrorResponse extension method in your Web API controller method to return meaningful error codes and error messages. Note that the CreateErrorResponse method creates an HttpError object and then wraps it inside an HttpResponseMessage object.

The following code listing illustrates how you can use the CreateErrorResponse extension method from your Web API controller action method.

public IActionResult GetEmployee(int id)
{
    Employee emp = employeeRepository.Get(id);
    if (emp == null)
    {
       string message = "Employee doesn't exist";
        throw new HttpResponseException(
            Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
    }
    return Ok(emp);
}

Refer to the GetEmployee() method shown above. This method accepts an employee ID as a parameter and uses this ID to search and retrieve an employee record using the employee repository instance. If an employee record having the specified employee ID is not found, an instance of HttpResponseException is thrown. Note how the appropriate error message and error code are constructed before the exception instance is thrown from the Web API controller method.

Using exception filters in ASP.Net Web API

Exception filters are filters that can be used to handle unhandled exceptions that are generated in your Web API controller methods. In other words, you can use exception filters to catch unhandled exceptions in Web API that originate from your controller methods. Note that a global error filter is a good approach to handling exceptions in your Web API if unhandled exceptions are thrown and not handled in your controller methods.

To create an exception filter, you need to implement the IExceptionFilter interface. You can also create exception filters by extending the abstract class ExceptionFilterAttribute and then overriding the OnException method. Note that the ExceptionFilterAttribute abstract class in turn implements the IExceptionFilter interface.

The following code snippet illustrates how you can create a custom exception filter by extending the ExceptionFilterAttribute class and then overriding the OnException method. Note how the standard exceptions thrown by your controller methods are captured by the custom exception filter and then converted to HttpStatusResponse objects with the appropriate HttpStatusCode.

public class CustomExceptionFilter : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            HttpStatusCode status = HttpStatusCode.InternalServerError;
            String message = String.Empty;
            var exceptionType = actionExecutedContext.Exception.GetType();
            if (exceptionType == typeof(UnauthorizedAccessException))
            {
                message = "Access to the Web API is not authorized.";
                status = HttpStatusCode.Unauthorized;
            }
            else if (exceptionType == typeof(DivideByZeroException))
            {
                message = "Internal Server Error.";
                status = HttpStatusCode.InternalServerError;
            }
            else
            {
                message = "Not found.";
                status = HttpStatusCode.NotFound;
            }
            actionExecutedContext.Response = new HttpResponseMessage()
            {
                Content = new StringContent(message, System.Text.Encoding.UTF8, "text/plain"),
                StatusCode = status
            };
            base.OnException(actionExecutedContext);
        }
    }

You should add the custom exception filter to the filters collection of the HttpConfiguration object.

public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            config.Formatters.Remove(config.Formatters.XmlFormatter);
            config.Filters.Add(new CustomExceptionFilter());
        }

You can register your exception filters in one of the following three ways:

  • At the action level
  • At the controller level
  • Globally

The following code snippet shows how you can apply a filter at the action level, i.e., to your controller action method.

public class EmployeesController : ApiController
{
    [NotImplementedExceptionFilter]
    public Employee GetEmployee(int id)
    {
        throw new NotImplementedException();
    }
}

To apply the exception filter at the controller level, you would need to use the filter attribute at the class level as shown below.

[DatabaseExceptionFilter]
public class EmployeesController : ApiController
{
    //Some code
}

You can also apply your custom exception filter globally so that it works for all of the Web API controllers. Here is how you can do this.

GlobalConfiguration.Configuration.Filters.Add(new DatabaseExceptionFilterAttribute());

The following code snippet illustrates how you can apply the custom exception filter we created earlier to your controller method.

[CustomExceptionFilter]
 public IEnumerable<string> Get()
 {
    throw new DivideByZeroException(); 
 }

ASP.Net Web API supports the use of HttpResponseException to handle exceptions both at the controller level and at the action level. When an action method in Web API throws an uncaught exception, the exception is translated to HTTP Status Code 500, i.e., “Internal Server Error.” If you use HttpResponseException, you can specify the status code you would like to return in the constructor of the HttpResponseException class. In this way you can customize your error codes to make them more meaningful.