Some people recommend making your software robust by working around problems automatically. This results in the software “failing slowly.” The program continues working right after an error but fails in strange ways later on. A system that fails fast does exactly the opposite: when a problem occurs, it fails immediately and visibly.
This quote is from Jim Shore’s great article “Fail Fast” (Published by the IEEE Computer Society). Although published 15 years ago, it is still very relevant today.
First of all, you have to accept failure. When you receive invalid or incomplete input, don’t try to work around it or assume — just fail. Fail as soon as possible.
A pattern I’ve adopted to deal with this, is the Guard pattern. Consider the following Action on an ASP.NET Core Controller:
From the get-go, it’s obvious what the Guards are for. Before handling the request, we make sure that both inputs are valid: id should not be an empty Guid and name should not be null or an empty string.
Initially, this is what my Guard statements looked like:
Easy enough: when a certain condition isn’t met, an Exception is thrown and further execution of the code stops — in other words: failing. Note that these Guards are the first statements in our Post action: we’re failing fast.
There’s one problem here though: we’re throwing exceptions, which will ultimately result in our API returning 500: Internal Server Error when left unhandled. That’s not right: I didn’t do anything wrong, you did!
Our API should ideally be returning a 400: Bad Request error. After all, the request isn’t valid!
The first step is to introduce a new type of exception, a GuardException:
Let’s update our Guards to throw GuardExceptions:
Now, to return a Bad Request error. Well, by the grace of exception-handling middleware in ASP.NET Core, we can add custom middleware to our request pipeline that listens for, and acts upon, these GuardExceptions.
Here’s what that looks like in our Startup.cs:
Admittedly, this code looks a bit clunky and verbose — I hope we will see some syntactic sugar for this in a future release of ASP.NET Core.
Essentially, what happens is this: we add a custom ExceptionHandler to our pipeline. In that handler, we request the IExceptionHandlerPathFeature feature (you can read more about ASP.NET Core Application Parts here) of ASP.NET Core.
Using some sweet C# pattern matching, we check whether the Error (if any) in the IExceptionHandlerPathFeature is a GuardException. If so, we return a BadRequest along with a JSON object comprising the faulty argument and a helpful message.
And that’s it! What I really like about these Guards is that they’re concise, their intent is clear and I can drop them anywhere in my code. When left unhandled, my API will appropriately return a BadRequest error.
Time for some shameless self-promotion: I’d strongly advise to keep this exception-handling code out of your Startup.cs and refactor it into an extension method. You can read more about this in my story Keeping Your ASP.NET Core Startup Project Clean.
👏 Thank you for reading this!👏
Fill in the form below and we’ll get back to you as soon as possible.
Thanks for getting in touch!Oops. You seem to have written your full name in invisible ink. Please enter it so we can read it. Oops. You seem to have written your company in invisible ink. Please enter it so we can read it. It seems your e-mail doesn’t exist. Please enter a real one so we can contact you. Oops. You seem to have written your telephone in invisible ink. Please enter it so we can read it. Sorry, we could not send the enquiry.