I have a chain of C# applications/services communicating through WCF, and one MVC web application that can sometimes instigate actions along this chain of services.
What I want is a safe way of reporting useful errors that happened along this chain, once a web app user instigated an action that resulted in an exception. My current solution is catching any Exception as soon as possible, then creating a CustomException with a custom message that best identifies the causing problem. This CustomException will propagate up the service chain (serialized at the service boundaries using a [FaultContract (typeof(SerialisedCustomException)]) by try/catch blocks. When an Exception is caught at any point, if it is of type CustomException it'll be rethrown. Otherwise a CustomException will be created on the spot, as above, then thrown further.
As a use-case, let's assume that a user logged in to my web application A performs an action which tells service B to tell service C to create a file on C's filesystem. (the actual actions are more complex than this, and more than one thing can go wrong, but I think this is a sufficient example)
If anything goes wrong along the way, I want the user to be informed of it in such a way that he can remedy the problem.
By safe, I want only errors that I have specifically created (hence my usage of a CustomException) be shown to the user, and nothing else (if a System exception, say UnauthorizedAccessException, gets thrown, I will wrap it in my own CustomException and only show the end-user the message of my own CustomException. I do not want any Exception messages that potentially expose implementation details be shown to the user.
By useful, I want to show the user an appropriate message and suggestion, such as 'make sure you have the right permissions etc.', as opposed to 'Service B says: Internal Server Error'. (These would be set the moment the CustomException is first thrown, and not altered on further catch/throws. If debugging is enabled, I'll be also displaying a stack-trace, but in production I will only show my safe custom message).
The problem with my approach is that the more and more I write try/catch blocks around my service methods, and in the methods they are calling, and so on, the eeriest I feel that this is not the right way to go, and that there's a better, more efficient/less bloated solution out there.
Is there anything that solves this problem while also avoiding the overhead of wrapping everything in try/catch blocks ?
Edit: Added justification for the need of reporting the errors rather than saying 'Something went wrong, we're looking into it.'
My web app can instigate complex (and customizable) actions on the lower-level services. These can fail for plenty of reasons which can be fixed by tweaking the customization of that action.
As an example, let's say I have an action that copies a a user-inputted source file to a user-inputted destination (on machine C, or on a network drive accessible to machine C). For various reasons (file not found, network down, lack of permissions, not enough disk space etc.), this action might fail, but some of the reasons could be fixed by the user changing that custom action, if only they were able to see why it failed in the first place.
You do not need to try...catch everything, you only need to catch only expected exceptions to wrap them in an CustomException and add a useful message to them, otherwise they should be catched in the caller (or caller of caller and so on) method.
Also you do not need to catch CustomException and re-throw it. It just bubbles up even if you don't catch it. Only problem is WFC Services throw FaultExceptions only. You can catch those exception in the most outer call only.
And to have useful exceptions, you can simply provide a detailed message for the exception, specify an ErrorCode property for CustomException or define nested exceptions like CustomException1 and CustomException2 inheriting CustomException. In the UI level you can resolve user friendly error message from that error code or exception type.
For example:
Web Application A:
void UserAction(string input) {
try {
serviceB.RespondToAction(input);
}
catch (FaultException e) {
if (e.InnerException is CustomException) {
DisplayMessageToUser(ResolveExceptionMessage((CustomException)e.InnerException));
}
}
catch (CustomException e) {
DisplayMessageToUser(ResolveExceptionMessage(e));
}
}
Service B:
void RespondToAction(string input) {
try {
SomeOperation(input);
}
catch (FormatException e) {
throw new CustomException("Invalid input format.", e);
}
// Note you do not catch CustomException here...
// Note you do not use try-catch here...
serviceC.CreateFile();
}
Service C:
void IOOperation2() {
try {
IOOperation();
}
catch (IOException e) {
throw new CustomException("Failed to create file.", e);
}
catch (SecurityException) {
throw new CustomException("Failed to create file.", e);
}
// Note you do not catch an ExecutionEngineException here...
}
From my experience exceptions are rarely useful for communicating information to the end user. 'make sure you have the right permissions etc.' sounds more like a business rule type of handling than exception type.
I don't often encounter the need to propagate exception through layers either. There are scenarios where that could be useful, but most of the time they can be logged at the site where they are caught.
And the caught clause is usually used very sparingly, that is it is not uncommon for a web application to only have a single global exception handler and that's it.
The main purpose of the exceptions is to tell the support personnel what have gone wrong. That mainly either a) infrastructure conditions (server is down, database is down, etc) or b) bug in the code. Everything else usually falls into the bucket of business errors and processed as such.
There are edge cases when the above is not enough, for example if you are consuming a service or a library that you don't have control over and this server/library makes use of exceptions to communicate results of an operation. But that's rare.
The way I design my exception handlers is to always start with a single global one (per application). Then if during testing exceptions are found, I look into them and try to classify them. Is this exception because of a bug? Then I fix the bug. Is this exception because of infrastructure condition? Then perhaps need to log it, show appropriate message to the customer and perhaps notify support. In this case a custom error handler can be warranted, however often a generic "we have a error we are looking into it" message and the support notification is enough, in this case a custom error handler is not needed either. Note that in the described situation the end user can't really do anything about the issue but wait. Lastly if the exception is because of business conditions then I see if I can re-design the code path so that no exception is thrown for business type errors. If it's my own code this is not a problem (and I won't have this situation to start with), if it's a library/service, then yes, might need to wrap the call into a try/catch.
As the result of the above approach my code have very few exception handlers, and I like it this way - if disaster happens it's usually immediately clear where as the stack trace pinpoints the exact location, and there is no messy nested exceptions to consider.
Note: for a library author the considerations could be slightly different
Related
I have asked a few questions on here and read a few articles around exception handling but don't think I'm really grasping when you should and when you shouldn't handle an exception. From the articles I've read it states to "only handle exceptions you can recover from" What does it mean by that. If I can't handle the exception what do I do? Let it propagate back up the stack? If I don't handle it how can I log it and present a user friendly error message. What do most people do in web apps and web services?
As an example say I have a lower tier data layer that pulls data from sql
try{
//do something with db
}catch(SqlException ex){
//what should i do here
//should i call code again to retry getting data from db
}catch(Exception ex){
//should i even catch exception of type exception
}
How do I handle exceptions in lower tiers? Should I just let the exception bubble up the tiers? If so then if I want to catch an exception of type sqlexception then I need a reference to the library sqlexception is part of but surely I shouldn't have to reference that library in a layer that has nothing to do with data access.
Some simple ground rules:
Handling an exception requires that the state of your program is exactly the same as it was before the code got started that caused the exception. You will need lots of catch and finally blocks that restore variables back to their initial state.
Only consider handling an exception if catching it allows the program to continue running in a meaningful way. Hard to do anything useful when the database server is off line for example, might as well stop the program.
If you need a human to take corrective action (you almost always do) then be sure that she has enough information to troubleshoot the problem. Let exceptions bubble up to the UI layer. Avoid interpreting exceptions (no "Could not update the database" for example), display the exact exception message and stack trace.
Implement a handler for AppDomain.CurrentDomain.UnhandledException and log or display the value of e.ExceptionObject. Helps to diagnose unhandled exceptions. And helps you avoid putting catch everywhere.
A hundred unhandled exceptions with a good diagnostic is better than one caught one that destabilizes the program so it generates bad data or causes other unrelated exceptions to be thrown.
Exception management is a large subject, so I'll only touch the surface here.
From the articles ive read it states to "only handle exceptions you can recover from" What does it mean by that.
If you don't know how to recover from a specific exception, then there's not usually any point in catching it. If it's a web app or service, the web server itself will deal with the logging and recovery.
In some cases, you need to catch exceptions so that you can a generic recovery, for example by cancelling or reversing a transaction. In that case, an acceptable approach is to
catch the exception, do the generic recovery, and then throw the exception again.
If i cant handle the exception what do i do. Let it propgate back up the stack?
Yes.
If i dont handle it how can i log it and present a user friendly error message. What do most people do in web apps and web services?
The web server will log the exception. If you want to present a user-friendly error message in a web app, you can catch/log at the highest level of the stack and re-direct to your error message. Again, I would try not to catch System.Exception - instead make a list of the exceptions that your app throws, and catch just these types before presenting a message tailored to each type. As the list of exception types grows, either prevent each new exception type by changing the code, or add a new catch for that exception type.
In a web service, you can create a custom exception and add that as a node to the generic exception that the web service will provide.
In your code example, I wouldn't use try...catch unless you're expecting an exception and you know what to do with it.
How do i handle exceptions in lower tiers. Should i just let the exception bubble up the tiers.
Yes.
Okay, this will be far too brief since it's still early in the morning here but i've been struggling with this same question so here is what I understand:
"only handle exceptions you can recover from"
My understanding here is that you get the exception to a level in your code where you can do something about it. In the case of your low level code, you would let the exception bubble back up into a layer where you could modify your 'process' to handle the exception and possibly try the process again. (I typically log the error right where it is thrown.)
I'm tasked with writing an Exception Handling Strategy and Guidelines document for a .NET/C# project I'm working on. I'm having a tough go at it. There's plenty of information available for how/when to throw, catch, wrap exceptions, but I'm looking for describing what sorts of things should go on inside the catch block short of wrapping and throwing the exception.
try
{
DoSomethingNotNice();
}
catch (ExceptionICanHandle ex)
{
//Looking for examples of what people are doing in catch blocks
//other than throw or wrapping the exception, and throwing.
}
Thanks in advance
It means exactly that. If you are expecting code you're running to throw an exception, and when that exception is thrown your code knows what went wrong and how to proceed, then catch the exception and handle it.
Basically, the rule exists to prevent anti-patterns like:
try
{
...
}
catch(Exception ex)
{
throw;
}
The catch here does nothing but add a speed bump to unwinding the call stack. If you don't actually want to do anything with the exception you're catching, you shouldn't even bother with the catch.
A related but far more valid case is where you don't care about the exception being thrown, but you need to clean up in all cases. In that case, skip the catch; you don't need it, just make it a try-finally block.
EDIT: To answer the question in the post, not just the subject, you could write a rule as follows: "Do not code a try-catch statement that does not do anything, or only rethrows the caught exception. All catch statements should perform some value-added action relating to the thrown exception."
For example, let's say you are trying to connect to a SQL Server instance using credentials supplied by the user when they log into your app. Dozens of things could go wrong, some of which you can't expect, some of which you should.
Server isn't responding - you can try again; perhaps call the connection method recursively in the catch, with a "retry counter" to break the otherwise infinite loop.
User failed authentication - show a friendly (or not-so-friendly, but concise and understandable) message in red on the dialog box.
User not authorized to connect to the specified DB - Depends on your security setup; in most offices, that's something you should e-mail the DBA about because it means he created the login but forgot to assign the proper rights.
Network not available: You can alert the user through an error on the login dialog or a new dialog, retry a couple of times, etc.
Division by zero - WTF? What could possibly cause a Div by Zero during a login? You're not expecting this exception, you have no clue what went wrong in this case and therefore can't continue running code, so don't catch it.
If anything goes wrong, you may want to log the message to a file or a shared resource for audit/security purposes. This should happen at lower levels if you want to continue execution, or higher levels if you're going to gracefully shut down afterward.
All of these examples involve first catching the exception of a known type and interrogating it to see what exactly went wrong, then performing some known action that can allow the program to continue execution. The object is to prevent the application from crashing and burning when something goes wrong that you know could go wrong, but know how to keep the program running in that case.
The basic rules for catching exceptions:
If you aren't expecting an exception, don't catch one.
If you can't or don't want to continue execution of code after receiving an exception, whether you know it can happen or not, don't catch it.
If you are expecting the exception to occur, and know-how to continue executing code when it happens (at least for a while), then catch and perform any special actions you need in order to do so.
NEVER trap exceptions (an empty catch block); that causes applications to fail silently in even more unpredictable ways.
NEVER leave catch-and-rethrow (a catch block with only a rethrow) in production code. They can sometimes be useful when debugging as they allow you to identify specific segments of code that are failing, but in production code, they're just a speed bump to throwing out or actually dealing with the exception.
I think the basic idea underlying this common piece of advice is to avoid scenarios like this:
try
{
SomeImportantResource = GetSomeImportantResource();
SomeOtherImportantResource = GetSomeOtherImportantResource();
}
catch (Exception ex)
{
SomeGlobalErrorHandlingMechanism(ex);
}
I've worked with developers who, when confronted with a bug, would simply wrap the offending code in a try/catch block and say, "I fixed the bug." The problem in scenarios like the above example is that by simply catching an exception and not fixing the problem that caused it, you're liable to undermine the solidity of your program. Above, what the catch has done is made us uncertain whether SomeImportantResource and SomeOtherImportantResource were ever initialized properly. It seems likely that there could be code elsewhere in the program that requires for these to be initialized, in which case, we've just introduced a bug by "fixing" a bug.
So I think the standard wisdom is to only try to deal with an exception if you can recover from it in such a way that it does not compromise any other code elsewhere in your program.
Or, better than that: don't catch the exception and make some feeble attempt (or non-attempt) to "handle" it; figure out what caused it and fix that problem. Obviously this is not always possible, but it is possible a lot more often than it should be.
Consider if you had an application like OneNote that lets you store your files on a shared network drive, but in the event the network is unavailable, then it uses local storage temporarily until the main storage is available.
If your program got an exception while interacting with the files, then you could retry the action with the local storage.
This is an example where you have a specific program behavior you want, and accomplish it by how you handle the exception. Generally, you should try to find a way to accomplish your goal without using exception handling, such as in the above exmple, you could always check to see if the file is available before attempting to operate on it. That way you can just code it as an "if/else" instead of a "try/catch". However, if you did that, there is still always the chance in the above case that someone may lose access to a file in the middle of an operation, such that regardless of whether you checked in advance, you still might get an exception that you can handle gracefully. So you'd probably refactor your else block into a function that is both called from the else and the catch, so that you can gracefully fallback to local storage in either case.
I also often include logging if there is no security issue with what I'm logging, and a rethrow as you mentioned, and my logging includes more descriptive information and context information, maybe some local values, which make debugging easier. I always strive to have log files so detailed that I can determine the cause of a problem without having to reproduce on my machine. I hate hearing programmers make the "I can't reproduce it" excuse. You don't have to reproduce it. If your logging is adequate then there is no need to reproduce it.
When an exception trickles up via rethrow's all the way to your GUI layer, then at that point is where you catch it and do not rethrow it, but instead display a message to the user indicating that an unexpected error occurred, and usually exit the application. You might give them an opportunity to save work, but maybe automatically making a backup of the file being overwritten, as an unhandled exception is something you never coded for, meaning something might be corrupt, and you might be saving a bad file, yet leading the user to believe they are saving their work. This is ultimately the reason many program opt to kill themselves if something unexpected occurs, as from that point on who knows what state the program might be in, and something as simple as saving some rows in a database might have serious consequences and hose alot of data.
If you can perform an action when you catch an exception that is helpful in some way (such as executing a block of code that will perform the function attempted in the try statement, but does it in a different, but perhaps less efficient way, or simply informing the user that their action couldn't be performed), then you should catch it and do so. If you are simply logging the exception to track down the problem later, then you should rethrow the exception throw; (NOT throw ex;), in case there is another block of code that can handle that type of exception.
It's also acceptable to catch an exception to wrap the caught exception in your own exception that may make more sense to the calling function.
Some examples:
Log the exception and just carry on
Retry the thing that went wrong
Try another method of doing what you were trying to do
It all depends on what went wrong. The point is, just catching and re-throwing is of no use to anyone.
If your code can gracefully handle a specific type of exception, catch it and handle it, and then let your code keep going. If not, let the exception propagate up, because it may be caught at a higher level or it may be something really wrong that you shouldn't be catching as it might mask the error.
You shouldn't catch an exception you can't handle, but you can catch exceptions that you might be able to handle:
try
{
DoSomethingNotNice();
}
catch (ExceptionIMightBeAbleToHandle ex)
{
if(iCanHandle(ex))
thenHandle(ex);
else
throw;
}
Note that using throw by itself is supposed to preserve stack trace info.
Typical things you can handle gracefully would be a FileNotFoundException.
The catch block should teardown anything that may have been opened for use in the try and due to the exception being thrown not closed down properly. Database connections and file access are the ones that usually need closing down (though proper use of a using block can handle this)
Once that has been done you can use throw; to chuck the exception up to the next level
Alternatively you might want to wrap your current exception inside a new exception more relevant to the current method
catch(LowLevelException ex){
throw new HighLevelException("argh bad things happened!",ex);
}
Coming late to the game but the MS recommended way to handle errors globally in .net core is middleware.
Also you can use a switch statement like this to make sure you re-throw errors you can't handle.
Trying to keep my answer as general as the question ;) but I can provide some code if needed.
Say, for example, that I have a PostsService that creates a post:
public class PostsService : IPostsService
{
public bool Create(Post post)
{
if(!this.Validate(post))
{
return false;
}
try
{
this.repository.Add(post);
this.repository.Save();
}
catch(Exception e)
{
return false;
}
}
}
The problem with this is that if an exception is thrown during the repository actions, it's swallowed. Create() returns false and all that the consumer knows is that the Post wasn't added, but doesn't know why.
Instead, I was think of having a ServiceResult class:
public class ServiceResult
{
public bool Success { get; private set; }
public Exception Exception { get; private set; }
}
Would this be a good design? Or do I even need to report these errors to the consumer? Is it sufficient to say "An error occurred while adding the post." and then log the exception inside of the service?
Any other suggestions are appreciated.
I think it depends on the scope of why. Some failure reasons shouldn't concern the consumer, in my opinion and these should be logged in the service. On the other hand, there are cases when the consumer should be informed of these reasons, so in addition to logging them, you should indicate the cause of the error somehow.
For instance, suppose a very common use case of a user registration service. It's quite likely that you'd have a unique attribute that identifies the user (user handle, email, etc). This uniqueness must be enforced by the service (and probably at a database level too). Now, if the consumer is trying to register a user and it fails because the constrain was violated, the consumer should be notified of this reasons (so it could try some other user handle). Failed validations fall in the same scenario, most of the times.
If there's some kind of internal DB problem on the other hand, the consumer should not be informed of the details (because that's exclusive responsibility of the service; and it's not something the consumer can do anything about anyway).
Considering that, I'd say returning a boolean is insufficient in many cases. So having some kind of ServiceResult type doesn't sound like a bad idea. I'm not sure I would include the Exception though. But perhaps you can create some kind of ServiceExpection, specific to your service. Sometimes error codes are just fine for this, too.
It's a really bad idea to catch all exceptions. You only catch that which you can reasonably handle. You can't handle all exceptions, so why are you catching it? To prevent a stack trace?
If you don't want your users to see a horrible stack trace, I get that, but you do want it to die and die horribly so that something isn't corrupted.
Let's say that service threw an OutOfMemoryException, you just caught it, and won't know whether or not your application is leaking memory like a sieve or is improperly allocating large objects.
That's a bad thing.
If you don't want your user to see what was wrong, then you should change your catch to say:
catch (Exception e)
{
//send it to yourself, log it. Just don't swallow it.
LogErrorAndEmailDevTeam(e);
throw new SaveFailedException("We're sorry. \n" +
"It's not your fault, but something bad happened.\n\n" +
"We've been notified and will fix it as soon as possible.");
}
But even better would be to let the application die a horrible death instead of catching that exception so that you know quickly when something goes wrong.
You don't want your application to continue in a corrupted state, but that's what catch (Exception) does. Are you really sure you can handle whatever is thrown?
Yes, the ServiceResult class is a good idea, but I wouldn't include an exception, there are times you want to report errors but you don't want/need to create/throw/catch an exception, instead I would include a collection of error messages or an enum type indicating what went wrong, something like MembershipCreateStatus.
Also, don't catch Exception, it can make bugs hard to find.
Keep in mind that one of the key benefits of a service oriented architecture is decoupling components of the system. The more the calling layers have to know about the service the more tightly coupled the layers become. Following this logic it is better to have the calling layer know as little as possible about the error, all it needs to know is that the service call failed.
Does the calling layer really need to know why the service failed? What can it really do about it? Is it just so you can show a better message to the user? In this case does the user really care about the detail? It's easy to think the user wants to know more, just because you as the developer does. But developers should be getting information about error messages from logs, not from end user messages.
(Disclaimer: In my experience I've worked a lot more with exposing/consuming services between environments, where the built-in functionality in something like WCF isn't always useful and one doesn't always have control over the client consuming the service.)
More and more in my service designs I've moved towards a request/response system. (Actually, I've made heavy use of the agatha-rrsl library in this regard.) In that design, I have a BaseRequest object and a BaseResponse object, from which all request and response types inherit.
Continuing with what you were thinking, that ServiceResult class would serve well as the start of such a BaseResponse. It doesn't necessarily need the actual exception, but a few things I tend to include are:
A bool indicating success or failure for any request, even one which returns actual results on success.
An IList<> of custom Message objects, which themselves contain a message type of some sort (Info, Warn, Error, etc.) as well as the message text (and perhaps an additional user-friendly message text for UI display needs), stack trace if relevant, etc.
Going further, I also like to include a few things in the BaseRequest such as the originating user, host, etc.
The idea is that the service itself should never throw a raw exception. Whoever is consuming the service should always expect to get a valid response, even if that response indicates a failure of some sort. It should expect some basic information to come back every time and know how to handle that information.
If you're using WCF, I'd recommend against a ServiceResult, or anything similar for dealing with exceptions in a SOA layer.
You should define a FaultContract for your method. This would allow consuming code to know about the types of exceptions that can be thrown and handle them accordingly using traditional try/catch blocks.
This StackOverflow question has a full implementation of Fault Contracts.
You could still have your front-end simply say "An error has occurred", but using a fault contract would allow for better error handling on the UI layer of your code if it becomes needed in the future.
I keep hearing that
catch (Exception ex)
Is bad practise, however, I often use it in event handlers where an operation may for example go to network, allowing the possibility of many different types of failure. In this case, I catch all exceptions and display the error message to the user in a message box.
Is this considered bad practise? There's nothing more I can do with the exception: I don't want it to halt the application, the user needs to know what happened, and I'm at the top level of my code. What else should I be doing?
EDIT:
People are saying that I should look through the stack of calls and handle errors specifically, because for example a StackOverflow exception cannot be handled meaningfully. However, halting the process is the worst outcome, I want to prevent that at all costs. If I can't handle a StackOverflow, so be it - the outcome will be no worse than not catching exceptions at all, and in 99% of cases, informing the user is the least bad option as far as I'm concerned.
Also, despite my best efforts to work out all of the possible exceptions that can be thrown, in a large code-base it's likely that I would miss some. And for most of them the best defense is still to inform the user.
The bad practice is
catch (Exception ex){}
and variants:
catch (Exception ex){ return false; }
etc.
Catching all exceptions on the top-level and passing them on to the user (by either logging them or displaying them in a message-box, depending on whether you are writing a server- or a client-application), is exactly the right thing to do.
I find the arguments that generic catches are always bad to be overly dogmatic. They, like everything else, have a place.
That place is not your library code, nor the classes you custom-develop for your app. That place is, as many have mentioned, the very top level of the app, where if any exception is raised, it is most likely unexpected.
Here's my general rule (and like all rules, it's designed to be broken when appropriate):
I use classes and custom-built libraries for the majority of the lifting in an app. This is basic app architecture -- really basic, mind you. These guys try to handle as many exceptions as possible, and if they really can't continue, throw the most specific kind available back up to the UI.
At the UI, I tend to always catch all from event handlers. If there is a reasonable expectation of catching a specific exception, and I can do something about it, then I catch the specific exception and handle it gracefully. This must come before the catch all, however, as .NET will only use the very first exception handler which matches your exception. (Always order from most specific to most generic!)
If I can't do anything about the exception other than error out (say, the database is offline), or if the exception truly is unexpected, catch all will take it, log it, and fail safe quickly, with a general error message displayed to the user before dying. (Of course, there are certain classes of errors which will almost always fail ungracefully -- OutOfMemory, StackOverflow, etc. I'm fortunate enough to have not had to deal with those in prod-level code ... so far!)
Catch all has its place. That place is not to hide the exception, that place is not to try and recover (because if you don't know what you caught, how can you possibly recover), that place is not to prevent errors from showing to the user while allowing your app to continue executing in an unknown and bad state.
Catch all's place is to be a last resort, a trap to ensure that if anything makes it through your well-designed and well-guarded defenses, that at a minimum it's logged appropriately and a clean exit can be made. It is bad practice if you don't have well-designed and well-guarded defenses in place at lower levels, and it is very bad practice at lower levels, but done as a last resort it is (in my mind) not only acceptable, but often the right thing to do.
When I see
catch (Exception ex)
my hand starts to groping for a hammer. There are almost no excuses to catch base Exception. Only valid cases that come to my mind are:
1) 3rd party component throws Exception (be damned it's author)
2) Very top level exceptions handling (as a last resort) (for example handle "unhandled" exceptions in WinForms app)
If you find a case where many different types of exceptions can happen it's a good sign of bad design.
I would disagree with Armin Ronacher. How would you behave if StackOverflow exception raised? Trying to perform additional actions can lead to even worse consequences. Catch exception only if you can handle it in meaningful and safe way. Catching System.Exception to cover range of possible exceptions is terribly wrong. Even when you are re-throwing it.
It makes complete sense to catch the exception at the highest level in your code. Catching the base Exception type is fine as long as you don't need to do any different logic based on the exception's type.
Also, make sure you're displaying a friendly, general error message and not showing the actual exception's message. That may lead to security vulnerabilities.
Yes, it is fine to catch the base Execption at the top level of the application, which is what you are doing.
The strong reactions you are getting is probably because at any other level, its almost always wrong to catch the Base exception. Specifically in an a library it would be very bad practice.
It is bad practice in the sense that you shouldn't do it everywhere.
In this case, I would consider it the only reasonable solution as your exception could be truly anything. The only possible improvement would be to add extra handlers before your catch everything for specific error cases where you could do something about the exception.
It's perfectly okay if you re-raise exceptions you can't handle properly. If you just catch the exceptions you could hide bugs in the code you don't expect. If you catch exceptions to display them (and bypass the die-and-print-traceback-to-stderr behavior) that's perfectly acceptable.
I think the poster is referring to exception handling like this:
try {something} catch (SqlException) {do stuff} catch (Exception) {do other stuff}
The idea here is that you want to catch the more specific errors (like SqlException) first and handle them appropriately, rather than always relying on the catch-all general Exception.
The conventional wisdom says that this is the proper way to do exception handling (and that a solo Catch (Exception ex) is bad). In practice this approach doesn't always work, especially when you're working with components and libraries written by someone else.
These components will often throw a different type of exception in production than the one your code was expecting based on how the component behaved in your development environment, even though the underlying problem is the same in both environments. This is an amazingly common problem in ASP.NET, and has often led me to use a naked Catch (Exception ex) block, which doesn't care what type of exception is thrown.
Structured exception handling is a great idea in theory. In practice, it can still be a great idea within the code domain that you control. Once you introduce third party stuff, it sometimes doesn't work very well.
We use Catch ex as Exception (VB.Net variant) quite a bit. We log it, and examine our logs regularly. Track down the causes, and resolve.
I think Catch ex as Exception is completely acceptabile once you are dealing with production code, AND you have a general way to handle unknown exceptions gracefully. Personally I don't put the generic catch in until I've completed a module / new functionality and put in specialized handling for any exceptions I found in testing. That seems to be the best of both worlds.
No; in that case if you don't want to halt the program there's nothing else you can do and at the top level is the right place to do it, as long as you're logging properly and not hiding it away in hope grin
The important thing is to understand the path of exceptions through your application, and not just throw or catch them arbitrarily. For example, what if the exception you catch is Out-Of-Memory? Are you sure that your dialog box is going to display in that case? But it is certainly fine to define a last-ditch exception point and say that you never want errors to propagate past that point.
You should catch the exceptions related to what you are doing. If you look at the methods you call, you will see what exceptions they throw, and you want to stay more specific to those. You should have access to know what exceptions may be thrown by the methods you call, and handle them appropriately.
And... better than having one big try catch, do your try and catch where you need the catch.
try {
myThing.DoStuff();
}
catch (StuffGoneWrongException ex) {
//figure out what you need to do or bail
}
Maybe not quite this closely packed, but it depends on what you are doing. Remember, the job isn't just to compile it and put it on someones desktop, you want to know what breaks if something did and how to fix it. (Insert rant about tracing here)
a lot of times exception are catched to free resources, it' s not important if exception is (re)thrown. in these cases you can avoid try catch:
1) for Disposable object you can use "using" keyword:
using(SqlConnection conn = new SqlConnection(connStr))
{
//code
}
once you are out of the using scope (normally or by a return statement or by exception), Dispsose method is automatically called on object. in other word, it' s like try/finally construct.
2) in asp.net, you can intercept Error or UnLoad event of Page object to free your resource.
i hope i help you!
I'm responding to "However, halting the process is the worst outcome..."
If you can handle an exception by running different code (using try/catch as control flow), retrying, waiting and retrying, retrying with an different but equivalent technique (ie fallback method) then by all means do so.
It is also nice to do error message replacement and logging, unless it is that pseudo-polite-passive-aggressive "contact your administrator" (when you know there is no administrator and if there was the administrator can't do anything about it!) But after you do that, the application should end, i.e. same behavior you get with an unhandled exception.
On the other hand, if you intend to handle the exception by returning the user to a code thread that has potentially trashed its state, I'd say that is worse than ending the application and letting the user start over. Is it better for the user to have to restart at the beginning or better to let the user destroy data?
If I get an unexpected exception in the module that determines which accounts I can withdraw money from, do I really want to log and report an Exception and return the user to the withdraw money screen? For all we know we just granted him the right to withdraw money from all accounts!
This is all good of catching exceptions that you can handled. But sometimes it also happens that due to unstable environment or users just do the process correctly, the application runs into unexpected exception. Which you haven't been listed or handled in code. Is there a way that the unhandled exception is captured from app.config file and displays a common error?
Also puts that details exception message in a log file.
I've been working a fair bit with exceptions, and here's the implementation structure I'm currently following:
Dim everything to Nothing / String.Empty / 0 etc. outside of Try / Catch.
Initialise everything inside Try / Catch to desired values.
Catch the most specific exceptions first, e.g. FormatException but leave in base Exception handling as a last resort (you can have multiple catch blocks, remember)
Almost always Throw exceptions
Let Application_Error sub in global.asax handle errors gracefully, e.g. call a custom function to log the details of the error to a file and redirect to some error page
Kill all objects you Dim'd in a Finally block
One example where I thought it was acceptable to not process an exception 'properly' recently was working with a GUID string (strGuid) passed via HTTP GET to a page. I could have implemented a function to check the GUID string for validity before calling New Guid(strGuid), but it seemed fairly reasonable to:
Dim myGuid As Guid = Nothing
Try
myGuid = New Guid(strGuid)
'Some processing here...
Catch ex As FormatException
lblError.Text = "Invalid ID"
Catch ex As Exception
Throw
Finally
If myGuid IsNot Nothing Then
myGuid = Nothing
End If
End Try
We're reviewing one of the company's system's exception handling and found a couple of interesting things.
Most of the code blocks (if not all of them) are inside a try/catch block, and inside the catch block a new BaseApplicationException is being thrown - which seems to be coming from the Enterprise Libraries.
I'm in a bit of a trouble here as I don't see the benefits off doing this. (throwing another exception anytime one occurs)
One of the developers who's been using the system for a while said it's because that class's in charge of publishing the exception (sending emails and stuff like that) but he wasn't too sure about it.
After spending some time going through the code I'm quite confident to say, that's all it does is collecting information about the environment and than publishing it.
My question is:
- Is it reasonable to wrap all the code inside try { } catch { } blocks and than throw a new exception? And if it is, why? What's the benefit?
My personal opinion is that it would be much easier to use an HttpModule, sign up for the Error event of the Application event, and do what's necessary inside the module. If we'd go down this road, would we miss something? Any drawbacks?
Your opinion's much appreciated.
Never1 catch (Exception ex). Period2. There is no way you can handle all the different kinds of errors that you may catch.
Never3 catch an Exception-derived type if you can't handle it or provide additional information (to be used by subsequent exception handlers). Displaying an error message is not the same as handling the error.
A couple of reasons for this, from the top of my head:
Catching and rethrowing is expensive
You'll end up losing the stack trace
You'll have a low signal-to-noice ratio in your code
If you know how to handle a specific exception (and reset the application to pre-error state), catch it. (That's why it's called exception handling.)
To handle exceptions that are not caught, listen for the appropriate events. When doing WinForms, you'll need to listen for System.AppDomain.CurrentDomain.UnhandledException, and - if your doing Threading - System.Windows.Forms.Application.ThreadException. For web apps, there are similar mechanisms (System.Web.HttpApplication.Error).
As for wrapping framework exceptions in your application (non-)specific exceptions (i.e. throw new MyBaseException(ex);): Utterly pointless, and a bad smell.4
Edit
1 Never is a very harsh word, especially when it comes to engineering, as #Chris pointed out in the comments. I'll admit to being high on principles when I first wrote this answer.
2,3 See 1.
4 If you don't bring anything new to the table, I still stand by this. If you have caught Exception ex as part of a method that you know could fail in any number of ways, I believe that the current method should reflect that in it's signature. And as you know, exceptions is not part of the method signature.
If I am reading the question correctly, I would say that implementing a try / catch which intercept exceptions (you don't mention - is it catching all exceptions, or just a specific one?) and throws a different exception is generally a bad thing.
Disadvantages:
At the very least you will lose stack trace information - the stack you will see will only extend to the method in which the new exception is thrown - you potentially lose some good debug info here.
If you are catching Exception, you are running the risk of masking critical exceptions, like OutOfMemory or StackOverflow with a less critical exception, and thus leaving the process running, where perhaps it should have been torn down.
Possible Advantages:
In some very specific cases you could take an exception which doesn't have much debug value (like some exceptions coming back from a database) and wrap with an exception which adds more context, e.g id of the object you were dealing with.
However, in almost all cases this is a bad smell and should be used with caution.
Generally you should only catch an exception when there is something realistic that you can do in that location- ie recovering, rolling back, going to plan B etc. If there is nothing you can do about it, just allow it to pass up the chain. You should only catch and throw a new exception if there is specific and useful data available in that location which can augment the original exception and hence aid debugging.
I'm from the school of thought where try/ catch blocks should be used and exceptions not rethrown. If you have executing code which is likely to error then it should be handled, logged and something returned. Rethrowing the exception only serves the purpose to re-log later in the application life cycle.
Here's an interesting post on how to use a HttpModule to handle exceptions: http://blogs.msdn.com/rahulso/archive/2008/07/13/how-to-use-httpmodules-to-troubleshoot-your-asp-net-application.aspx and http://blogs.msdn.com/rahulso/archive/2008/07/18/asp-net-how-to-write-error-messages-into-a-text-file-using-a-simple-httpmodule.aspx
Check out ELMAH. It does what you're talking about. Very well.
When I create libraries I try to always provide a reduced number of exceptions for callers to handle. For example, think of a Repository component that connects to a sql database. There are TONS of exceptions, from sql client exceptions to invalid cast exceptions, that can theoretically be thrown. Many of these are clearly documented and can be accounted for at compile time. So, I catch as many of them as I can, place them in a single exception type, say a RepositoryException, and let that exception roll up the call stack.
The original exception is retained, so the original exception can be diagnosed. But my callers only need to worry about handling a single exception type rather than litter their code with tons of different catch blocks.
There are, of course, some issues with this. Most notably, if the caller can handle some of these exceptions, they have to root around in the RepositoryException and then switch on the type of the inner exception to handle it. Its less clean than having a single catch block for a single exception type. I don't think thats much of an issue, however.
Sounds like the exception that is thrown should not have been implemented as an exception.
Anyway, I would say that since this BaseApplicationException is a general all-purpose exception, it would be good to throw exceptions that are more context-specific. So when you are trying to retrieve an entity from a database, you might want an EntityNotFoundException. This way when you are debugging you do not have to search through inner exceptions and stack traces to find the real issue. If this BAseApplicationException is collecting information on the exception (like keeping track of the inner exception) then this should not be a problem.
I would use the HttpModule only when I could not get any closer to where the exceptions are actually happening in code. You do not really want an HttModule OnError event that is a giant switch statement depending on BaseApplicationexception's error information.
To conclude, it is worth it to throw different exceptions when you can give more specific exceptions that tell you the root of the problem right off the bat.
From my experience, catch the exception, add the error to the Server (?) object. This will allow .NET to do what ever it needs to do, then display your exception.