How to handle errors in Web API

Learn how you can handle runtime errors in your Web API using exceptions and return appropriate error code and error messages back to the pipeline

Error handling in Web API

Error handling in Web API

ASP.Net Web API is a lightweight framework from Microsoft that can be used for building 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. You should have a good idea of how you can handle exceptions in Web API and send out appropriate error codes and error messages from your Web API controller methods.

Using HttpResponseException

You can use the HttpResponseException class to return specific HTTP status code and messages from your controller methods in Web API. Here's 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;

}

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

Using HttpError

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 Employee 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 emp;

}

Refer to the GetEmployee() method shown above. It accepts an employee Id as 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 is constructed before the exception instance is thrown from the Web API controller method.

Using Exception filters

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 can originate from your controller methods. Note that a global error filter is a good approach to handle 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 piece of code 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 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 the Web API controllers. Here's how you can do this.

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

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(); 

 }

This article is published as part of the IDG Contributor Network. Want to Join?

To comment on this article and other InfoWorld content, visit InfoWorld's LinkedIn page, Facebook page and Twitter stream.
From CIO: 8 Free Online Courses to Grow Your Tech Skills
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.