
Force Web API to Fail with ActionFilter
Sometimes, what you really want is failure.
Success is great. Hooray! The crowds roar at your continued success. But in reality, everything is not peachy. Developers choose to ignore failure planning to their peril. Me? I need ASP.NET Web API to fail.
In one of my projects, I utilize the ASP.NET Web API for the heavy lifting. My JavaScript and jQuery code make a lot of AJAX calls to the API and so far, I’ve got all of the success handlers written. That’s great as long as my code never experiences a problem. Ship it!
No. Don’t ship it.
I need to ensure that my UI handles errors well. We can either write the error handlers and pray to the software gods or do something to force the error. If it’s a database call, for example, we could do something drastic and disconnect the machine from the network or change the connection string to ensure that something goes wrong.
That’s way too much work.
The New ActionFilter
The easiest way I’ve found of forcing an error is to create an ActionFilter and apply it to the class or method you want to fail. The web is full of ActionFilter examples to catch errors, but that’s not what we want. We want to create an HttpResponseException and let the JavaScript (or other client) that called the API deal with it.Note that an ActionFilter for a Web API controller is slightly different than the one for standard MVC. It's in the System.Web.Http.Filters namespace instead.
Here’s the Web API ActionFilter I created to automatically error out the API call:
namespace MyProject
{
///
/// <summary>
/// An error message to be sent in the description of the error.
/// </summary>
public string ErrorMessage;
/// <summary>
/// How long of a delay to introduce before the error occurs. Use to simulate timeouts.
/// </summary>
public int Delay = 0;
private const string DefaultErrorMessage = "Automatic error generated. This is caused by the FailRequest ActionFilter. To stop this error, remove the attribute from the class or method.";
public override void OnActionExecuting(HttpActionContext filterContext)
{
if (ErrorMessage == null)
{
ErrorMessage = string.Format("{0}. This error was fired on the {1} Action of the {2} Controller.",
DefaultErrorMessage, filterContext.ActionDescriptor.ActionName,
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName);
}
Thread.Sleep(Delay);
throw new HttpResponseException(filterContext.Request.CreateErrorResponse(StatusCode, ErrorMessage));
}
}
}
Note that an ActionFilter for a Web API controller is slightly different than the one for standard MVC. It’s in the System.Web.Http.Filters namespace instead. Check out MSDN for more information on Web API ActionFilters.
Since the Web API does its best to be RESTful, we need the ability to send the client an error of any type: 404 Not Found, 400 Bad request, 500 Internal Server Error. Whatever. So, the first parameter is a specific HttpStatusCode. By setting this we can test how your client code responds to different errors. It defaults to 500.
We can customize the error message that is sent. By default it sends a message that informs the caller that the FailRequest filter is applied and that’s the source of the error. It tells what controller and action the fail request came from.
Timeout, Man
Additionally, it takes in an optional delay time in milliseconds. This is useful in simulating a problem that may occur due to a timing issue on the server. If we want to test timeout handlers on the client, setting an arbitrarily high delay would allow us to test in a realistic manner without making any code changes inside the actual controller code or the client code.It’s simple and clean. Optionally, we could set up conditional compilation so that the action filter only activates when we’re in a special debug mode. This would keep it from errantly ending up in production code. What do you think?