Let's build an error handling aspect: part 6
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 only works for ITerritoryService
- Swallowing exceptions: we should at least be logging the exception, not just ignoring it.
- If the method has a return type, then it's returning null. If it's meant to return a reference type, that's probably fine, but what if it's returning a value type?
- What if it's returning a collection, and the UI assumes that it will get an empty collection instead of a null reference?
- Do we really want to return the exception message to the user?
- What if I forget to use ServiceBase as a base class on a new service?
- Unit tests: how to test this aspect in isolation.