Once I've added all of my robust error handling-features to my exception classes, I am now positioned to easily determine faults, should they arise. However, there is more than just providing the error-handling mechanisms. You must also provide a model to follow for how exceptions will be handled by answering some of the questions below:
Where is the exception handled?
When should you log an error?
Will the exception be “remoted?”
Who will be the final receiver of the exception?
What protocols and transports is the receiver using?
This section discusses the answers to these questions and will provide you with a starting point upon which to build an exception boundary policy.
Throwing Exceptions from Web Services
In most Web applications, the last boundary of properly-handling exceptions is controlled by the ASP.NET or Web service code. In most cases, throwing exceptions from a Web service can be done in the same manner as throwing exceptions from anywhere else. You simply throw an exception from the Web method, and .NET takes care of the rest. If SOAP is used to call the Web method, .NET automatically wraps your exception in a corresponding SoapException class, nesting your original exception within it. However, in many cases the details of that wrapped exception may not suit your client application. For example, wrapping the exception in this manner may not provide the level of detail your clients require. This is especially true when the message protocol used is SOAP. Thankfully, there is a way to circumvent this automated wrapping by throwing your own SOAP exceptions in cases where custom-detailed information may be required. Figure 2.3 should give you a good visual of how exceptions are wrapped inside of a SoapException class. Notice there is no loss in the amount of detail because all information is preserved through chaining.
Figure 2.3. Wrapping SOAP exceptions: How base exceptions are wrapped by SoapExeptions.
This should by no means discourage the client from using SOAP—quite the contrary. Unless messages passed to Web services are rather simple and, thus, using a HTTP GET or POST is sufficient, I suggest using SOAP as your message protocol for passing data. Using SOAP will provide you with the most flexibility in passing complex types, such as DataSet, to your prospective Web services. With .NET, you do not have to even determine which message protocol is used. Using this wrapping technique, .NET detects the message protocol and will wrap your thrown exception in a SoapException class. However, the details provided are sparse, at best. This is especially true with SOAP Fault information. In these cases, the best practice is to throw your own SoapException. For those SOAP 2.0 clients, this means they will receive a properly formatted SOAP Fault on the client with as much detail as required. A SOAP Fault is a mechanism used to determine the details of the exception in a “SOAP-compliant” manner, such as the following technology backgrounder describes. A SOAP Fault is not simply used for low-level errors but can be the means by which all exceptions are determined, as we will see in the upcoming implementation pattern.