How to catch exceptions - c#

This is my first application that will deal with exceptions properly. It's a WCF service. All the other before were simple apps just for myself. I have very small knowledge about exception handling in C#.
I have a code like this:
MembershipUser memUser = Membership.GetUser(username);
DatabaseDataContext context = new DatabaseDataContext();
UserMembership user = UserMembership.getUserMembership(memUser);
ItemsForUser itemUser = Helper.createItemForUser(ref item, memUser);
Helper.setItemCreationInfo(ref item, user);
context.Items.InsertOnSubmit(item);
context.SubmitChanges();
In this code a few exceptions can happen. Like NullReferenceException for example. How do I know which object caused the exception so I can know what to do in the catch and what to return to the client?

In general, you should not catch any exceptions.
I know this sounds strange, but the fact is that you should only catch exceptions you can actually do something about, and you usually can't do anything about exceptions.
The "exceptions" to this rule have to do with what it means to "handle" an exception. In some applications, "handling" the exception means to log it. In others (ASP.NET, for instance), it's better to not handle the exception, because the framework (ASP.NET Health Monitoring in this case) will log it for you.
In event-driven code, like Windows Forms, I find it's necessary to catch exceptions within event handlers. At least in earlier versions of .NET, allowing the exception to propagate outside of, for instance, a button click event produced unpleasant results. I typically catch the exception and display it in a dialog box.
In a multi-tier application, one might catch exceptions on tier boundaries, then rethrow a new, tier-specific exception:
try
{
// ...
}
catch (Exception ex)
{
throw new TierException("Some message", ex);
}
Another use case is to catch the exception, then throw a new exception with more information in it:
public int GetValueFromConfigurationFile(...)
{
const string configFileName = "...";
try
{
// ...
}
catch (FileNotFoundException fEx)
{
throw new InvalidOperationException(
String.Format("Can't find configuration file {0}", configFileName),
fEx);
}
}
In this case, you are catching a specific exception (FileNotFoundException), and providing your caller information they could not otherwise know: that the file not found was a configuration file.
The general message is:
- Only catch exceptions you know how to handle
- Catch the most specific exception possible
- Always include the inner exception when creating a new exception, to preserve the chain of exceptions
- To rethrow the current exception, use throw;, not throw ex;
There are a few more, and I'll try to find you the reference from the Microsoft Framework Design Guidelines.
P.S. If someone can find the question this is a duplicate of, feel free to close as a duplicate. I don't mind losing any rep from this. I just couldn't find the duplicate.
I should have just posted the link to the "exception-handling" tag wiki, where it says:
However, for exception handling in the context of .NET programs, see
"Design Guidelines for
Exceptions".

Although WCF has mechanisms for passing server exceptions through to the client it is probably worth considering if your client user really wants to see typically complex server side exceptions in their face.
In general better to trace server side expections - and if you want access to that remotely then use a remote tracing logger. Or have a single text trace api on your server to log server exceptions client side in an unobtrusive fashion.

Related

Where should I place try catch?

Learning to log errors.
This is a basic structure of code all through my project.
I have been advised that the try block has to be placed only in Event Handlers.
But when logging the error, it is required to know, which method caused the error.
So, in such cases, should I also keep try block in AllIsFine() & SaveData().
If yes, then should it log the error or just throw.
What is the best/Standard practice.
DataContext objDataContext = new DataContext();
protected void btn_Click(object sender, EventArgs e)
{
try
{
if(AllIsFine())
{
objDataContext.SaveData();
}
}
catch(Exception ex)
{
//some handling
}
}
private bool AllIsFine()
{
//some code
}
EDIT: Ofcourse, we would try to see that it never raises an exception, but not practical. I am looking at it this way. When deployed, the only access I have is to the logs and need to get as much info as possible.So in such cases, (and with this kind of a structure), where do you advise to keep the try catch
I have been advised that the try block has to be placed only in Event
Handlers
This is not true.
There are different type of exceptions, some you need to handle, some you should throw, some you should catch, some you should not. Read this please.
Summary:
You should catch exceptions that you can do something with them
If you want to just log exceptions catch, log, and then use throw not throw ex (it resets the call stack)
Prevent exception from happening if you can, check for conditions that prevent exceptions(IndexOutOfRangeException, NullPointerException, ArgumentNullException) do that instead of executing the action and catch the exception
Don’t catch fatal exceptions; nothing you can do about them anyway, and trying to generally makes it worse.
Fix your code so that it never triggers a boneheaded exception – an "index out of range" exception should never happen in production code.
Avoid vexing exceptions whenever possible by calling the “Try” versions of those vexing methods that throw in non-exceptional
circumstances. If you cannot avoid calling a vexing method, catch its
vexing exceptions.
Always handle exceptions that indicate unexpected exogenous conditions; generally it is not worthwhile or practical to anticipate
every possible failure. Just try the operation and be prepared to
handle the exception.
But when logging the error, it is required to know, which method
caused the error.
You should use the call stack for that.
Try as much as possible to Prevent the Exceptions, and not catching them, if you would Catch an error, try to catch a specific Error, what I mean by that, not try to Catch Exception but something like specific like InvalidCastException.
After catching an Error you should log the exception, but not throwing an exception to log it.
The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions.
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
It is possible to use more than one specific catch clause in the same try-catch statement. A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement. You can catch one exception and throw a different exception. When you do this, specify the exception that you caught as the inner exception
catch (FileNotFoundException ex)
{
// FileNotFoundExceptions are handled here.
}
catch (InvalidCastException ex)
{
// Perform some action here, and then throw a new exception.
throw new YourCustomException("Put your error message here.", ex);
}
throw ex; is basically like throwing an exception from that point, so the stack trace would only go to where you are issuing the throw ex; statement
I thought about your question for a while and even if it is already answered, I wanted to share my thoughts.
general
When talking about exception handling, you have to keep in mind what an exception is:
An exception occurs when code cannot run as expected, causing an inconsistent behaviour/state of your application.
This thought leads us to an important rule: Do not catch exceptions that you can’t handle! The Exception system provides security. Think about an accounting software that connects to a database and the connection throws an exception. If you only log the exception and don’t provide any notification about this to the user, he will start to work with the software and when he tries to save, the data will be lost!
You see, it is important where to handle exceptions:
Some of them will be handled by the user (usually in the UI-Layer e.g. View in MVVM/MVC) like the Database exception from the example – only the user can decide if the database is required, the connection string has changed or if a retry will fix the issue.
Others can be handled where they occur; for example code that interacts with some sort of hardware often implements methods with some sort of retry or circuit-breaker logic.
architecture
The where decision is also influenced by the architecture:
Let’s come back to the Database exception scenario: You cannot handle specific exceptions like a MySQL specific Exception (MySqlException) in the UI-Layer because that causes a boundary from you View layer to the specific Model layer implementation and the layering architecture will be broken. However, this is not the topic since your question is about logging exceptions, but you should keep that in mind and probably think about it like this: Catch exceptions of concrete libraries or those that belong to a specific layer/dependency where they occur and log them there and throw new, more generic (probably self-created) exceptions. Those exceptions can be handled in the View-layer and presented to the user.
implementation
The question of where is also important. Since logging is seen as a cross cutting concern. You could think about an AOP framework or, as I have suggested in a comment, by using a decorator pattern. You can compose the logging decorators by basic inversion of control usage and your code will be much cleaner by wrapping everything in try-catch blocks.
If you are using (or planning to use) a DI-container in your application, you could also make use of interception, which would allow you to dynamically wrap you method calls by specified behaviour (like try-catch).
summary
handle your exceptions where you can handle them and log them where you get the most relevant data (e.g. context) from to reproduce the error. But keep in mind that an exception is a security mechanism – it will stop your application when it is no longer in a secure state – when you don’t forward your exceptions (by using throw) and just log them, this could cause not the best user experience.
If you want any code examples, simply ask for them ;)

Handling of exceptions, do I have to catch each specific exception?

Just a thing I've been thinking of for a while. Do I need to handle KeyNotFoundException by catching that specific exception or can I just use a "blank" catch like this:
try
{
//Code goes here
}
catch
{
}
Or do I have to do it like this:
try
{
//Code goes here
}
catch(Exception ex)
{
}
Or do I have to do it like this:
try
{
//Code goes here
}
catch(KeyNotFoundException ex)
{
}
The reason why I ask is that when I look at crash count at App Hub I have a lot of crashes related to "KeyNotFoundException" but I never experience any crashes in my app. Could this be the problem, that I don't catch the specific exception and that App Hub crash statistics classifies it as a crash even if the exception is handled?
EDIT:
Here are some screenshots of the App Hub crash statistics (Stack Trace). Does anyone know ehat in detail it means? It has to do with my background agent and that might be the reason for why I never experience any crashes in my app:
No, the marketplace is counting only unhandled exceptions, so your app does crash.
An empty catch or catching Exceptions are the most general catches (Every exception is derived from the Exception base class, so you're catching everything.), the critical code is somewhere you don't use try-catch. Based on the exception you should check your dictionaries and think about what are the conditions which can cause error.
Generally a good practice is to check the correctness of parameters in your public methods so if any problem occurs you can provide yourself more helpful error messages, for example:
public User GetUser(string username)
{
if (String.IsNullOrEmpty(username))
throw ArgumentNullException("username");
return this.users[username];
}
In this case if things goes wrong you will see that you used a null for username, otherwise you would see a KeyNotFoundException. Hope this helps, good luck!
You can use a base exception to catch a more derived exception, so Exception will catch KeyNotFoundException because the latter inherits the former. So strictly speaking, if you want to catch "any" exception, catch (Exception) will suffice.
However, you should only catch exceptions if you can handle them in some meaningful manner. Though I'm not sure how this mindset stacks up against WP development.
As for your underlying problem, I've no idea. Does the App Hub not provide any details around the crash such as stack traces?
Your best bet is to leave the template code in place that registers for the unhandled exceptions event and put some logging into your application to record as much detail as you can about the state of the app during the crash.
No, you do not have to catch each specific exception type in a try / catch block, see the C# language reference.
However, rather than wrapping all your code in try / catch blocks, you probably want to add exception handling logic and logging into a handler for the Application.UnhandledException event. See this excellent blog post for an example of how to handle this event.
If you are interested in a specific exception, such as KeyNotFoundException in a particular part of the code then you catch it like this
try
{
//Code goes here
}
catch(KeyNotFoundException ex)
{
}
If you want to catch a specific exception and some undefined one you do something like this
try
{
//Code goes here
}
catch(KeyNotFoundException ex)
{
}
catch(Exception ex)
{
}
If you want to make sure your application doesn't crash use Collin's example with the Application.UnhandledException event.
You can catch all exceptions by catching the base class, but whether you want to depends on what your trying to achieve.
Generally speaking, you should only catch an exception at a level at which you have the knowledge to decide what should be done about the error, ie roll back some action, or display a message to the user. It is often the case that at a certain level it makes sense to catch a specific exception type, as that level of code understands what that means, but it may not make sense to catch all.
Avoid catching everything too soon, exceptions exist to tell you somethings wrong, blanket catching ignores that and can mean your program keeps running, but starts behaving wrong, possibly corrupting data. Its often better to "fail early and fail fast" when receiving unexpected exceptions.
As others have said - No - you dont need to catch the specific exception, catching Exception or just catch will prevent the exception from bubbling up.
However you should just catch specific exceptions where possible to make your code more explicit in what it is doing. Better again test for correctness before the potential error condition - again this is covered in other posts.
For your specific problem the link you posted seems to indicate that it is a problem with reading values from the isolated storage (IsolatedStorage.get_Item) - so wherever you access IsolatedStorage during from the ScheduledTaskAgent invocation you need to ensure the item exists before getting it. Perhaps there are some config settings missing or something?

C# exception handling, which catch clause to use? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Catching specific vs. generic exceptions in c#
Here's an example method
private static void outputDictionaryContentsByDescending(Dictionary<string, int> list)
{
try
{
//Outputs entire list in descending order
foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value))
{
Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
I would like to know what exception clause to use apart from just Exception and if there is an advantage in using more specific catch clauses.
Edit: O.k thanks everyone
Catching individual types of Exceptions in your statement will allow you to handle each in a different way.
A blanket rule for Exception may be useful for logging and rethrowing Exceptions, but isn't the best for actually handling Exceptions that you may be able to recover from.
try
{
// open a file specified by the user
}
catch(FileNotFoundException ex)
{
// notify user and re-prompt for file
}
catch(UnauthorizedAccessException ex)
{
// inform user they don't have access, either re-prompt or close dialog
}
catch(Exception ex)
{
Logger.LogException(ex);
throw;
}
You should only really catch exceptions that you are expecting that code may throw. That way, if it throws something you didn't expect, it may either be something critical; something that should bubble up the call stack and possibly crash the application; or something you have not thought of.
For example, you may wish to handle IOExceptions thrown by I/O code so that you can relay the problem back to the user. However, the same operations may throw something more critical such as an AccessViolationException. In this case, you might want the program to terminate, or handle the problem in a different way.
Generic exception handling should only really be used in cases where you do not care what error occurred, and subsequently don't want it affecting the rest of your process.
The only potential cause for an exception that I see in your example is if list is null. OrderByDescending() should return an empty IEnumerable<> rather than a null reference.
If I read that correctly, it might make more sense to catch NullReferenceException:
try
{
...
} catch (NullReferenceException exception)
{
MessageBox.Show(...);
}
However, this really depends on the needs of your application. If your intention is just to alert the user or to log all exceptions, catching the Exception class is fine. If you need special handling for different types of exceptions - such as sending an email alert instead of just logging the message - then it makes sense to use specific exception types:
try
{
}
catch(NullReferenceException e)
{
//...
}
catch(StackOverflowException e)
{
//...
}
catch(Exception e)
{
/// generic exception handler
}
Which exception to use really depends on the code in the try block. In general you want to catch exceptions that you can do something with and let exceptions you have no power over move to high levels of your code where you can perform some action that makes since. One of the most common mistakes I see people make is attempting to catch errors that they have no ability to handle.
for example
Void ChoseFile()
{
try
{
string FileName = GetInputFile()
}
catch( InvalidFileSelectedException ex)
{
//In this case we have some application specific exception
//There may be a business logic failure we have some ability
//to infomr the user or do an action that makes sense
}
catch(FileNotFoundException exfilenot found)
{
//In this case we can do somthing different the the above
}
catch(Exception )
{
//Normal I would not use this case we have an error we don't know what to do
//with. We may not have a usefull action. At best we can log this exception
// and rethrow it to a higher level of the application that can inform the user
// fail the attempted action. Catching here would only suppress the failure.
}
}
You should always catch exceptions with an as specific class as possible.
If you know what to do if a file is locked, but you regard all other errors as unexpected and impossible to handle, you should catch System.IO.IOException and deal with the error. You should only catch Exception (or just catch {) for gracefully exiting.
Since you are dealing with a Dictionary.. then you want to look at these 2 exceptions
The key of keyValuePair is a null reference (Nothing in Visual Basic).
ArgumentException An element with the same key already exists in the Dictionary(TKey, TValue).
KekValuePair Exception
This is taken from the MSDN site
Use the exception type that you might expect but still not be able to prevent and that you can adequately handle. Let anything else bubble up to somewhere that might expect it or can handle it.
In your case here, I might expect that I would run into a NullReferenceException if the dictionary is null. But I would not catch it. This is something I can validate against instead
if (dictionary != null)
So there is no reason to allow an exception to even happen. Never use exceptions for control flow, and validate against known causes.
Some classes/methods will throw different exceptions, depending on the error. For example, you might be using the File class to write data to a file. You could write multiple Catch statements for the exception types you could recover from, and a generic Exception catch to log and bubble up anything that can't be recovered from.
By using Exception you catch all exceptions. Of you use IOException or StackOverflowException you'll only catch errors of that type.
a StackOverflowException catched by a Exception still hold the same message, stack trace etc.
Exception handling philosophy
I am sure you can find many other philosophies
Code defensively. Catching exceptions is more expensive than preventing the error in the first place.
Don't catch an exception and bury it by not handling it. You can spend many hours trying to find an error that has been suppressed.
Do log errors that you catch.
This helps in analyzing the problem. You can check to see if more than one user is having the same problem
I prefer a database for logging, but a flat file, or the event log are also suitable.
The database solution is easiest to analyze but may introduce additional errors.
If the error is due to bad data entered by the user, inform the user of the problem and allow them to retry.
Always allow an escape route if they cannot fix the problem.
Catch the error as close to the source as possible
This could be a database procedure, a method in a data access layer (DAL) or some other location.
Handling the exception is different than catching it. You may need to rethrow the exception so that it can be handled higher up the stack or in the UI.
Rethrowing the exception can be done in at least two ways.
throw by itself does not alter the stack.
throw ex does alter or add to the stack with no benefit.
Sometimes it is best not to catch an exception, but rather let it bubble up.
If you are writing services (web or windows) that do not have a user interface (UI) then you should always log the error.
Again, this is so that someone can analyze the log or database file to determine what is happening.
You always want someone to know that an error has occurred.
Having a lot of catch statements for a try block can make your code more difficult to maintain, especially if the logic in your catch blocks is complex.
Instead, code defensively.
Remember that you can have try catch blocks within catch blocks.
Also, don't forget to use the finally block where appropriate.
For example, closing database connections, or file handles, etc.
HTH
Harv

Exception handling in n-tier applications?

What is the suggested approach or best practice for handling exceptions in tiered applications?
Where should you place try/catch blocks?
Where should you implement logging?
Is there a suggested pattern for managing exceptions in n-tiered applications?
Consider a simple example. Suppose you have a UI, that calls a business layer, that calls a data layer:
//UI
protected void ButtonClick_GetObject(object sender, EventArgs e)
{
try {
MyObj obj = Business.GetObj();
}
catch (Exception ex) {
Logger.Log(ex); //should the logging happen here, or at source?
MessageBox.Show("An error occurred");
}
}
//Business
public MyObj GetObj()
{
//is this try/catch block redundant?
try {
MyObj obj = DAL.GetObj();
}
catch (Exception ex) {
throw new Exception("A DAL Exception occurred", ex);
}
}
//DAL
public MyObj GetObj()
{
//Or is this try/catch block redundant?
try {
//connect to database, get object
}
catch (SqlException ex) {
throw new Exception("A SQLException occurred", ex);
}
}
What criticisms would you make of the above exception handling?
thanks
My rule of thumb is generally to catch exceptions at the top level and log (or otherwise report) them there, because this is where you have the most information about the the error - most importantly the full stack trace.
There may be some reasons to catch exceptions in other tiers, however:
The exception is actually handled. Eg. a connection failed, but the tier re-tries it.
The exception is re-thrown with more information (that isn't already available from looking at the stack). Eg. the DAL might report which DB it was trying to connect to, which SqlException wouldn't tell you.
The exception is translated into a more general exception that is part of the interface for that tier and may (or may not) be handled higher up. Eg. the DAL may catch connection errors and throw a DatabaseUnavailableException. The BL may ignore this for operations that are not critical or it may let it propogate for those that are. If the BL caught SqlException instead it would be exposed to the implementation details of the DAL. Instead the possibility of throwing DatabaseUnavailableException is part of the interface of the DAL.
Logging the same error at multiple tiers is generally not useful, but I can think of one exception: when a lower tier doesn't know whether a problem is critical or not it can log it as a warning. If a higher tier decides that it is critical it can then log the same problem as an error.
Here are a few rules I follow related to exception handling:
exceptions should only be caught in the layers that can implement the logic for handling them. Most of the cases this happens in the upmost layers. As a rule of thumb, before implementing a catch inside a layer, ask yourself if the logic of any of the upper layers depends in any way on the existence of the exception. For example in your business layer you might have the following rule: load data from an external service if the service is available, if not load it from the local cache. If calling the service throws an exption you can catch and log it at BL level and then return the data from the cache. The upper UI layer does not have to take any action in this case. However, if both the service and the cache call fail the exception would have to go to the UI level so that an error message can be displayed to the user.
all exceptions inside an application should be caught and if there is no special logic for handling them, they should be at least logged. Of course, this does not mean that you have to wrapp the code from all methods in try/catch blocks. Instead any application type has a global handler for uncaught exceptions. For example in Windows Applications the Application.ThreadException event should be implemented. In ASP .Net applications the Application_Error event handler from global.asax should be implemented. These places are the upper most locations where you can catch exceptions in your code. In many applications this will be the place where you will catch most of the exceptions and besides logging, in here you will probably also implement a generic and friendly error message window that will be presented to the user.
you can implement try/finally functionality where you need it without implementing a catch block. A catch block should not be implemented if you do not need to implement any exception handling logic. For example:
SqlConnection conn = null;
try
{
conn = new SqlConnection(connString);
...
}
// do not implement any catch in here. db exceptions logic should be implemented at upper levels
finally
{
// finalization code that should always be executed.
if(conn != null) conn.Dispose();
}
if you need to rethrow an exception from a catch block do that by simply using throw;. This will ensure that the stack trace is preserved. Using throw ex; will reset the stack trace.
if you need to rethrow an exception with another type that would make more sense for the upper levels, include the original exception in the InnerException property of the newly created exception.
if you need to throw exceptions from your code use meaningful exception types.
The first thing to fix would be to never throw a general Exception.
The second, unless there's really a good reason to wrap an exception, just have throw; instead of throw new... in your catch clause.
The third (and this isn't a hard & fast rule), don't catch general Exceptions at any point below the UI layer. The UI layer should catch general Exceptions so that a user-friendly message can be displayed to the end user, not the technical details of what blew up. If you catch a general exception deeper in the layers it's possible for it to be swallowed unintentionally and makes for bugs that are quite difficult to track down.
Exception handling is difficult in any application. You need to think about each and every exception and quickly get into a pattern that works for you. I try and group exceptions into one of the following categories...
Exceptions that should only happen if your code is wrong (or you don't understand, or you don't have control over them):
Example: Maybe your persistence framework requires you to catch SQL exceptions that could arise from malformed SQL, however, you're executing a hard coded query.
Handling: In my experience most exceptions fall in this category. At the very least, log them. Even better, send them to an exception handling service which logs them. Then in the future if you decide you want to log them differently or do something differently with them you can change it in one place. Maybe you also want to send a flag up to the UI layer saying that some kind of error occurred and they should retry their operation. Maybe you mail an administrator.
You will also need to return something to the higher layers so that life on the server goes on. Maybe this is a default value, or maybe this is null. Maybe you have some way of canceling the entire operation.
Another choice is to give the exception handling service two handling methods. A handleUnexpectedException() method would notify the user but not rethrow an exception and you could then return a default value if you have the ability to unwind the stack yourself or continue on in some way. A handleFatalException() method would notify the user and rethrow some kind of exception so that you can let the exception throwing unwind the stack for you.
Exceptions that are actually caused by the user:
Example: The user is trying to update a foobar widget and give it a new name, but a foobar widget already exists with the name they want.
Handling: In this case you need to get the exception back to the user. In this case you can go ahead and keep throwing the exception (or better, don't even catch it) until it reaches the UI layer and then the UI layer should know how to handle the exception. Make sure to document these exceptions so that you (or whomever is writing your UI) is aware that they exist and knows to expect them.
Exceptions that you can actually handle:
Example: You make a remote service call and the remote service times out but you know they have a history of doing so and you should just redo the call.
Handling: Sometimes these exceptions start off in the first category. After your application has been in the wild for a while you realize that you actually have a good way to handle it. Sometimes, like with exceptions from optimistic locking or interrupted exceptions, catching the exception and doing something with it is just a part of business. In these cases, handle the exception. If you're language (I'm thinking Java) distinguishes between checked and unchecked exceptions I would recommend these always be checked exceptions.
To address your above question I would delegate the initial exception to a service that would notify the user and depending on what kind of object MyObj is (e.g. settings) I might let this be a non-fatal exception and return a default value or if I can't do that (e.g. user account) then I might let this be a fatal exception so I don't have to worry about it.
I am with sepearate exception Class for each layer (DALException,BLException,...) to log (e.g: in file) the exceptions at the layer boundaries (this is for administrator) ,because user only should see clear and understandable error message. those exception should deal with on DAlBase which inherirted by all Data access layer calsses an so on all layers. with that we can centralize the exception handling in few class and the developer will only throw layerexception (e.g: DALException)
see more information MultiTier Exception Handling.

Should I catch exceptions only to log them?

Should I catch exceptions for logging purposes?
public foo(..)
{
try
{
...
} catch (Exception ex) {
Logger.Error(ex);
throw;
}
}
If I have this in place in each of my layers (DataAccess, Business and WebService) it means the exception is logged several times.
Does it make sense to do so if my layers are in separate projects and only the public interfaces have try/catch in them?
Why? Why not? Is there a different approach I could use?
Definitely not. You should find the correct place to handle the exception (actually do something, like catch-and-not-rethrow), and then log it. You can and should include the entire stack trace of course, but following your suggestion would litter the code with try-catch blocks.
Unless you are going to change the exception, you should only log at the level where you are going to handle the error and not rethrow it. Otherwise your log just has a bunch of "noise", 3 or more of the same message logged, once at each layer.
My best practice is:
Only try/catch in public methods (in general; obviously if you are trapping for a specific error you would check for it there)
Only log in the UI layer right before suppressing the error and redirecting to an error page/form.
The general rule of thumb is that you only catch an exception if you can actually do something about it. So at the Business or Data layer, you would only catch the exception in situation's like this:
try
{
this.Persist(trans);
}
catch(Exception ex)
{
trans.Rollback();
throw;
}
My Business/Data Layer attempts to save the data - if an exception is generated, any transactions are rolled back and the exception is sent to the UI layer.
At the UI layer, you can implement a common exception handler:
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Which then handles all exceptions. It might log the exception and then display a user friendly response:
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
LogException(e.Exception);
}
static void LogException(Exception ex)
{
YYYExceptionHandling.HandleException(ex,
YYYExceptionHandling.ExceptionPolicyType.YYY_Policy,
YYYExceptionHandling.ExceptionPriority.Medium,
"An error has occurred, please contact Administrator");
}
In the actual UI code, you can catch individual exception's if you are going to do something different - such as display a different friendly message or modify the screen, etc.
Also, just as a reminder, always try to handle errors - for example divide by 0 - rather than throw an exception.
It's good practice is to translate the exceptions. Don't just log them. If you want to know the specific reason an exception was thrown, throw specific exceptions:
public void connect() throws ConnectionException {
try {
File conf = new File("blabla");
...
} catch (FileNotFoundException ex) {
LOGGER.error("log message", ex);
throw new ConnectionException("The configuration file was not found", ex);
}
}
Use your own exceptions to wrap inbuild exception. This way you can distinct between known and unknown errors when catching exception. This is usefull if you have a method that calls other methods that are likely throwing excpetions to react upon expected and unexpected failures
you may want to lookup standard exception handling styles, but my understanding is this: handle exceptions at the level where you can add extra detail to the exception, or at the level where you will present the exception to the user.
in your example you are doing nothing but catching the exception, logging it, and throwing it again.. why not just catch it at the highest level with one try/catch instead of inside every method if all you are doing is logging it?
i would only handle it at that tier if you were going to add some useful information to the exception before throwing it again - wrap the exception in a new exception you create that has useful information beyond the low level exception text which usually means little to anyone without some context..
Sometimes you need to log data which is not available where the exception is handled. In that case, it is appropriate to log just to get that information out.
For example (Java pseudocode):
public void methodWithDynamicallyGeneratedSQL() throws SQLException {
String sql = ...; // Generate some SQL
try {
... // Try running the query
}
catch (SQLException ex) {
// Don't bother to log the stack trace, that will
// be printed when the exception is handled for real
logger.error(ex.toString()+"For SQL: '"+sql+"'");
throw; // Handle the exception long after the SQL is gone
}
}
This is similar to retroactive logging (my terminology), where you buffer a log of events but don't write them unless there's a trigger event, such as an exception being thrown.
If you're required to log all exceptions, then it's a fantastic idea. That said, logging all exceptions without another reason isn't such a good idea.
You may want to log at the highest level, which is usually your UI or web service code. Logging multiple times is sort of a waste. Also, you want to know the whole story when you are looking at the log.
In one of our applications, all of our pages are derived from a BasePage object, and this object handles the exception handling and error logging.
If that's the only thing it does, i think is better to remove the try/catch's from those classes and let the exception be raised to the class that is responsible on handling them. That way you get only one log per exception giving you more clear logs and even you can log the stacktrace so you wont miss from where the exception was originated.
My method is to log the exceptions only in the handler. The 'real' handler so to speak. Otherwise the log will be very hard to read and the code less structured.
It depends on the Exception: if this actually should not happen, I definitely would log it. On the other way: if you expect this Exception you should think about the design of the application.
Either way: you should at least try to specify the Exception you want to rethrow, catch or log.
public foo(..)
{
try
{
...
}
catch (NullReferenceException ex) {
DoSmth(e);
}
catch (ArgumentExcetion ex) {
DoSmth(e);
}
catch (Exception ex) {
DoSmth(e);
}
}
You will want to log at a tier boundary. For example, if your business tier can be deployed on a physically separate machine in an n-tier application, then it makes sense to log and throw the error in this way.
In this way you have a log of exceptions on the server and don't need to go poking around client machines to find out what happened.
I use this pattern in business tiers of applications that use Remoting or ASMX web services. With WCF you can intercept and log an exception using an IErrorHandler attached to your ChannelDispatcher (another subject entirely) - so you don't need the try/catch/throw pattern.
You need to develop a strategy for handling exceptions. I don't recommend the catch and rethrow. In addition to the superfluous log entries it makes the code harder to read.
Consider writing to the log in the constructor for the exception. This reserves the try/catch for exceptions that you want to recover from; making the code easier to read. To deal with unexpected or unrecoverable exceptions, you may want a try/catch near the outermost layer of the program to log diagnostic information.
BTW, if this is C++ your catch block is creating a copy of the exception object which can be a potential source of additional problems. Try catching a reference to the exception type:
catch (const Exception& ex) { ... }
This Software Engineering Radio podcast is a very good reference for best practices in error handling. There are actually 2 lectures.
It's bad practice in general, unless you need to log for very specific reasons.
With respect in general log exception, it should be handled in root exception handler.

Categories