Determining Appropriate Exception Policies and Actions
This information provides an overview of managing exceptions in your applications. For complete design and implementation guidelines for creating exception management systems that use .NET technologies, see Design Guidelines for Exceptions on MSDNĀ®.
To build successful and flexible applications that can be maintained and supported easily, you must use an appropriate strategy for exception management. You must design your system to make sure that it can do the following:
- Detect exceptions
- Log and report information
The following topics provide useful advice about how you should develop your exception management strategies:
- Generate Events That Can Be Monitored Externally to Help System Operation
- Exception Handling Process and the Exception Handling Application Block
- When to Catch Exceptions
- Exception Propagation
- Hiding Exception Information
- Exception Notification
- Planning for Exception Handling
Generate Events That Can Be Monitored Externally to Help System Operation
If you spend time at the beginning to design a clear and consistent exception management system, it frees you from having to piece together your system during development, or worse still, from having to retrofit exception handling into an existing code base.
An exception management system must be well encapsulated and must decouple the details of logging and reporting from the application's business logic. It must also be able to generate metrics that can be monitored by operators to provide an insight into the current health and status of the application. This helps create an application that can quickly and accurately notify operators of any problems it is experiencing. It can also provide valuable information to help developers and support services resolve problems.
Exception Handling Process and the Exception Handling Application Block
Figure 1 illustrates the basic steps that your application should perform to handle an exception.
Figure 1
Exception handling process
Each method or procedure in your application code should follow this process to ensure that exceptions are handled within the appropriate context defined by the scope of the current method. This process continues to occur as an exception propagates up the call stack.
When to Catch Exceptions
A method should catch exceptions only when it has to perform one or more of the following actions:
- Gather information for logging.
- Add any relevant information to the exception.
- Execute cleanup code.
- Try to recover.
If a particular method does not have to perform one or more of these actions, the method should not catch the exception. Instead, it should allow the exception to propagate back up the call stack. This keeps your code clean and explicit because each method catches only those exceptions that must be handled within the scope of that particular method and allows all other exceptions to continue to propagate.
Exception Propagation
There are three main ways to propagate exceptions:
- Let the exception propagate automatically. With this approach, you do nothing and deliberately ignore the exception. This causes control to move immediately from the current code block up the call stack until a catch block with a filter that matches the exception type is found.
- Catch and re-throw the exception. With this approach, you catch and react to the exception, and clean up or perform any other required processing within the scope of the current method. If you cannot recover from the exception, you re-throw the same exception to your caller.
- Catch, wrap, and throw the wrapped exception. As an exception propagates up the call stack, the exception type becomes less relevant. When an exception is wrapped, a more relevant exception can be returned to the caller. This is illustrated in Figure 2.
Figure 2
Propagating exceptions
With this approach, you catch the exception. This lets you react to the exception, clean up, or perform any other required processing within the scope of the current method. If you cannot recover, wrap the exception in a new exception and throw the new exception back to the caller. The InnerException property of the Exception class explicitly lets you preserve a previously caught exception. This allows the original exception to be wrapped as an inner exception inside a new and more relevant outer exception. The InnerException property is set in the constructor of an exception class.
When you use the Exception Handling Application Block, you propagate exceptions by using policies that you configure. For more information about configuring policies, see Entering Configuration Information.
Hiding Exception Information
For Web services that are exposed to external companies and systems, you may not want all exception information exposed to the clients. An exception should be thrown to the clients so that they can react, but you may not want all of the details of each exception to be sent outside your company. You may want to throw an exception that indicates only that the service is currently experiencing problems.
In this case, you should create a generic application exception that contains any information you want to convey. After catching an unhandled exception in your Web service, you should log the exception, perform any required processing, and then construct a new instance of the generic application exception. You can then set any information you want in the generic application exception and throw it to the client. This lets you log detailed information in the Web service and throw a less detailed exception to your clients.
When you use the Exception Handling Application Block, you hide exception information by using a replace handler. For more information about hiding exception information, see the Replacing an Exception scenario.
Exception Notification
Notification is a critical component of any exception management system. Logging is important in helping you understand what went wrong and what must be done to correct the problem, but notification informs you about the condition in the first place. Without correct notification, exceptions can go undetected.
The notification processes adopted by your application must be decoupled from your application code. You should not have to change code every time you have to change your notification mechanism, such as when you alter the list of recipients. Your application must communicate error conditions and rely on a decoupled monitoring system to identify those errors and take the appropriate action.
If your application is not going to run in an environment that uses a monitoring system, you have several options for creating notifications from your application. Either way, you have to work closely with any operations personnel or the monitoring system developers to define the correct procedures for monitoring and sending notifications.
When you use the Exception Handling Application Block, you notify users by using a custom handler. For more information about notifying users, see the Notifying the User scenario.
Planning for Exception Handling
After you define your application architecture, you should determine how the exceptions generated by your application will be handled. The strategy should be to meet all security, privacy, and performance requirements. The following are general guidelines for an exception handling strategy:
- Do not catch exceptions unless some kind of value can be added. In other words, if knowing about the exception is of no use to the user, to you, or to the application, do not catch it.
- Do catch exceptions if you want to retry the operation, add relevant information to the exception, hide sensitive information contained in the exception, or display formatted information.
- Generally, handle exceptions only at an application boundary (such as the top of a logical layer, tier, the boundary of a service, or at the top of a UI layer). Also, replace exceptions that contain sensitive information with new exceptions that contain information that can be exposed safely outside the current boundary.
- Do not propagate sensitive information across trust boundaries. This is a standard security consideration, but it is frequently overlooked when dealing with exception information. Instead, replace exceptions that contain sensitive information with new exceptions that contain information that can be exposed safely outside the current boundary.
- Make exceptions as accurate as possible and allow for specific actions to be taken when the exception is raised. Sometimes this may require writing custom exceptions with the required attributes.
- Error messages that are displayed to users should be relevant and they should suggest the corrective action to take. In most cases, user-displayed error messages should never contain sensitive information, such as stack traces or server names.