C# and asp.net error handling best practices? [duplicate]
Possible Duplicate:
Best practices for exception management in JAVA or C#
I am using class libraries and I try to put maximum c开发者_开发知识库ode in class libraries so that it can be reused in other projects.
Please advice me where I should put try catch blocks in class library functions or in front end forms (aspx pages) ?
Kindly also share what are best practices for handling errors.
Answering exactly to what you are asking, try-catch
blocks are used to handle exceptions, so you should put them where you will actually be handling the exception.
This can be a bit subtle, so let me put some example: imagine you have some method to do something with a file, and the path to the file is given as an argument. There may happen many bad things on that situation:
If the file can't be found, or it can't be open (ex: permissions issues, blocked by some procoess, etc), then it's the caller's and not the callee's fault, and the exception produced is already a description of the problem: let it propagate.
If the file is not in the expected format (for example, you get some int.Parse()
calls failing because there should be a number but there isn't), it's still the caller's fault (it passed you a path to a bad file, how mean!), but the inner exception is not accurate of the problem; here the catch-wrap-throw
pattern works best: you catch the exception, wrap it into a more descriptive exception type (ie, create a new exception of the good type, and put the old one as it's InnerException
), and throw that one: the caller doesn't care about which task within your code failed, it should care about why it failed.
Now, let's tweak the scenario a bit for the last case: let's assume your library tries to read some optional configuration files, at a pre-defined location. If loading any of these fails, the exception should be handled by the library itself, falling back to using the default options or whatever.
In summary: if the exception is a direct consequence of the caller doing something wrong, let it propagate. If it's an indirect consequence (for example, passing the path to the wrong file), use catch-wrap-rethrow
to tell the caller what it did wrong, rather than how it broke your code's logic. And if it's a signal to an unusual but foreseeable condition that you are able to handle, then you just handle it. In addition to that, you can do some "sanity checking" at the start of some methods and preventively throw a descriptive exception when you know some of the argument values will cause trouble, instead of waiting to the trouble actually arising (so this is an alternative to the catch-wrap-rethrow
when the issue can be detected early).
Back on the client code (the code that uses your API
), exceptions should be handled ASAP. Take that literally: as soon as possible, but not before it is actually possible. For example, a function that acts just as a wrapper to another one (a "home-made" curry) shouldn't try to handle exceptions triggered by the arguments it got passed, unless it can actually fix the issue and retry. Example (extremely generic):
void DoSomethingEasily(object someArgument) {
MyAPI.DoSomething(someArgument, "some-predefined-string-argument");
}
// ... somewhere else on the code ...
DoSomethingEasily(myObject);
In that scenario, handling exceptions from MyAPI.DoSomething
can be a split work: if the exception is caused by the "some-predefined-string-argument"
alone, then it's DoSomethingEasily
's job to handle it. If the exception is caused by myObject
, then DoSomethingEasily
shouldn't mess up and let the outer code deal with their own trouble.
If there is some exception that is not caused by the arguments (for example, caused by some state of the API, or by external factors such as a device failing), the ASAP idea applies again: if DoSomethingEasily
has enough information / context to be able to deal with these cases, then it definitely should. If it can't, however, it'll be better to not get in the way so the code calling it has a chance to deal with the problem.
Bonus suggestion: regardless of the case (reason), any exception thrown by your API
should always be documented. If you are using C#
with the Visual Studio IDE, then it's quite advisable to use the built-in XML comment documentation format, so the exceptions (and their description) will show up on Intellisense's tooltips.
Hope this helps.
Exceptin handling is a mechanism to prevent of returing (bad) results from one method to another and to isolate the exceptions from results.
For example you may call a method of your class library (named A) from UI, then A calls B and B calls C. Now there is a runtime problem in C method (Runtime exception). You could return something to B and say hey! there is an error here, then B should do the same for A and A for upper one too... You see! you could just throw an exception in C then you dont need to catch it in B neither in A. Then you just put a try-catch block when calling A method in some upper layers and simply report the error without need to put any extra if statements. Of course there are some situations which you have to put your try-catch block in your class library (Ex. When you faced to an exception which is concerned only with your class library not the higher layers).
As my experience, the catchs should be placed in the nearest place to the UI where you can report it in a good and minimal way. So the "throw statements" should be more than "catch statements" in your class library.
Of course you can implement your own Exception classes for better error handling (see here).
And also a try/catch should "only" be used when talking to external services, where you have no control over the results. Otherwise when you DO have control you should avoid causing exceptions and have a "return null" approach where no objects are available etc. Just a design tips ;)
精彩评论