After I wrote Common Pitfalls When Handling Exceptions in .NET, I had a few questions about exception handling techniques when you’re writing a Web Service. Of course the common pitfalls still apply. The questions were more around how you should expose those exceptions to the client of a Web Service. Should you let them percolate up and allow the SOAP stack to transform them into SoapFaults? Or should you catch all exceptions in each WebMethod and manually transform them into appropriate SoapFaults? I would definitely recommend using the second technique of catching all exceptions and manually transforming them into SoapFaults. What difference does it make, you might ask? There are two main reasons – the first related to your “contract” and the second related to security.
Let’s talk about Web Service contracts. Your contract – what you are promising to clients of your Web Service – is anything that you expose to the outside world. Typically developers think of this as the methods, parameters, and return values of your Web Service, but it also includes any SoapFaults that your Web Service can throw. You don’t want to let your implementation details (i.e. exceptions that can be thrown) leak into your Web Service contract. Does your client care if the Web Service is written in .NET, Java, C++, or hand-coded assembly language? They shouldn’t. If you allow the SOAP stack to transform exceptions into SoapFaults, you are allowing your underlying implementation details to leak into the contract. Your clients may start depending on the fact that a particular exception is being thrown and transformed into a particular SoapFault. What happens if you want to switch implementations later – for instance switching from ASP.NET Web Services (aka ASMX )to Windows Communication Foundation (WCF)? You will end up breaking client code. Best case scenario (for you, the Web Service developer) is that all the clients update their code to handle the changed SoapFaults. Worst case scenario (from your point of view) is that the install base is too large and you have to replicate ASMX exception-to-SoapFault semantics in WCF.
The second concern is security-related. By allowing exceptions to escape your web service and allowing the SOAP stack plumbing to serialize the exception, you are exposing implementation details, such as stack traces, that could assist a hacker in abusing your service. A good practice is to catch all exceptions in the WebMethod and provide meaningful (and sanitized) SoapFaults to your clients, but record detailed exception information, such as stack traces, using your favourite logging framework.