In the last post in the series, I moved the error handling aspect into an opinionated one by using Exceptionless and handling certain types of exceptions (like SqlException and NotImplementedException).
In this post, I'm going to go even further down the opinionated road and talk about exception recovery.
My goal is for any exception to be caught and logged, and we're already there. In addition, I'd like the user not to see a yellow screen, so I'm generally not allowing the exception to bubble up, in lieu of a nice error message being put into ModelState (or some other error handling). However, this might not be enough. If the service method throwing an exception has a return value, then it's likely that another error will happen later in execution (maybe due to a null reference). For example:
If the method doesn't throw an exception, everything is fine. If it does throw an exception, there will a null reference when I attempt to use the Count property. What I would prefer is that an empty collection is returned. In fact, this fits with the recommendations from Framework Design Guidelines (page 256) to always return an empty collection (or array) instead of null. I've added a helper method to construct the return value in case this occurs.
What about if the service method is not returning a collection? And what if it's returning a value (like int or DateTime)? It's okay to return a null in the first case. In the second case, it might be okay to throw an exception. I have so few of these in the project I'm working on that I don't worry about it much, but for the sake of completeness, let's just make it return the default value.
I need to be very cautious about what I'm doing, and wrap everything in a try/catch so that I don't end up causing another unhandled exception in my exception handling code. It would be a good idea to create some unit tests to make sure everything is behaving as expected.
Okay, I think one or two more posts will wrap it up for this series. We need to discuss whether or not the exception message should be shown to a user (hopefully you're leaning towards "no").
This seems like a lot of over-architecting for a problem that could be solved by having your service return Enumerable.Empty
The aspect is catching and logging the error (see posts 1 through 5), so the aspect is where I have to have it return an empty collection. But, I wonder if using Enumerable.Empty() would work instead of Activator.CreateInstance.
Matthew D. Groves lives in Central Ohio. He works remotely, loves to code, and is a Microsoft MVP.