Exception handling is a critical process for every software application. Imagine an application where users often see weird errors or an application that is constantly crashing. When exceptions remain unhandled, your application is quickly heading toward demise. Fortunately, as long as exceptions are handled correctly they are recoverable, and you’ll learn how as you read on.
This article focuses on handling exceptions using a global exception handler with a C# Web API, plus:
Errors and exceptions are terms that are often interchanged by developers, but the two have distinct differences. An error occurs when system resources are lacking or unavailable. Exceptions arise due to a problem within the program.
To clear up any confusion, here are more detailed descriptions of the differences between the two:
Errors in C# are complex failures that a programmer can’t handle, because they are caused by lacking or unavailable resources – out of memory, stack overflow and many others. Since programmers can’t handle errors using the C# program, these errors are deemed irrecoverable.
Exceptions usually occur due to a problem in the C# program. Exceptional conditions that require special handling or processing cause these problems. Unlike errors, exceptions are recoverable. In handling exceptions in C#, programmers use the try, catch and block method.
Armed with the difference between errors and exceptions, it’s now time to learn how to handle these exceptions.
For our discussion, let’s focus on exception handling with the ASP.NET Web API. ASP.NET, developed by Microsoft to build dynamic web applications or websites, is an open-source web framework. This framework runs using the C# programming language.
Going back to exception handling, when an exception is thrown in a Web API, the exception is translated into an HTTP response displaying a status code 500- “Internal Server Error.” How do you handle the exception?
HttpError object provides a way to return error information and messages to the client. To implement this, you need to place CreateErrorResponse to create an instance of HttpError object. Then it returns as HttpResponseMessage object.
public HttpResponseMessage Get([FromODataUri] int key) { Product data = context.Product.Where(k => k.Id == key).FirstOrDefault(); if (data == null) { string message = string.Format("No Product found with ID = {0}", key); return Request.CreateErrorResponse(HttpStatusCode.NotFound, message); } return Request.CreateResponse(HttpStatusCode.OK, data);; }
HttpResponseException enables the program to return HttpResponseMessage to the client. This exception returns HttpStatusCode specified in the exception constructor.
throw new HttpResponseException(HttpStatusCode.NotFound);
Or construct the entire response message for more control over the response:
public Product Get([FromODataUri] int key) { Product data = context.Product.Where(k => k.Id == key).FirstOrDefault(); if (data == null) { var response = newHttpResponseMessage(HttpStatusCode.NotFound) { Content = newStringContent(string.Format("No Product found with ID = {0}", key)), ReasonPhrase = "Product Not Found" }; throw new HttpResponseException(response); } return data; }
With exception filters, you can customize how your Web API handles several exceptions by writing the exception filter class. Exception filters catch the unhandled exceptions in Web API. When an action method throws an unhandled exception, execution of the filter occurs. However, the exception filter does not catch HttpresponseExecution since the latter is designed to return the HttpResponse.
You can use the exception filter once the controller action method throws an unhandled exception that is not an HttpResponseExeption.
namespace WebAPITest { using System.Net; using System.Net.Http; using System.Web.Http.Filters; public class CustomExceptionFilter: ExceptionFilterAttribute { public override void OnException(HttpActionExecutedContextactionExecutedContext) { string exceptionMessage = string.Empty; if (actionExecutedContext.Exception.InnerException == null) { exceptionMessage = actionExecutedContext.Exception.Message; } else { exceptionMessage = actionExecutedContext.Exception.InnerException.Message; } //We can log this exception message to the file or database. var response = newHttpResponseMessage(HttpStatusCode.InternalServerError) { Content = newStringContent(“An unhandled exception was thrown by service.”), ReasonPhrase = "Internal Server Error.Please Contact your Administrator." }; actionExecutedContext.Response = response; } } }
Now you know that the exception filter catches the unhandled exceptions. However, there are some exceptions raised from outside the action, such as: Error inside the exception filter, Exception related to routing, Exception inside the Message handler class, Exception in the controller constructor.
When this situation occurs, you will need exception handlers. Fortunately, Web API 2 can implement a global exception handler in your C# Web API. Web API provides “ExceptionHandler,” which implements the IExceptionHandler. To implement the ExceptionHandler, you can use the following code:
namespace WebAPITest { using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Web.Http.ExceptionHandling; using System.Web.Http.Results; public class GlobalExceptionHandler: ExceptionHandler { public async override TaskHandleAsync(ExceptionHandlerContext context, CancellationTokencancellationToken) { // Access Exception using context.Exception; const string errorMessage = "An unexpected error occured"; var response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, new { Message = errorMessage }); response.Headers.Add("X-Error", errorMessage); context.Result = new ResponseMessageResult(response); } } }
Note: The exception handler should be registered. Web APIs have an existing exception handler class but don’t support multiple exception handlers. Therefore, you need to replace the existing class with your custom exception handler class.
Retrace is an application performance monitoring (APM) solution that combines several tools in one, including performing code-level server monitoring, performance profiling, application monitoring, error tracking and many more.
One of Retrace’s exceptional features is error monitoring. With Retrace, you can collect C# exceptions within your application without compromising your code. It’s true! You can catch exceptions with no code changes.
What’s even better is that Retrace works with all ASP.NET applications and runs with MVC, WCF, Web API, .NET Core and many more.
Find every exception in your code. START YOUR FREE TRIAL NOW!
If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]