Browsing Posts in Web Services

I’m doing some WCF work for a client, specifically around WS-Security. I stumbled upon the System.ServiceModel.MessageSecurityVersion class today. Its static properties alone should explain why developers are craving simpler technologies like REST…

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.

Don Box provides a succint summary on the whole SOAP vs. REST debate. I couldn’t agree with him more!

Now that VS 2005 and .NET 2.0 has been released, the torrential flow of tool updates to .NET 2.0 has started. Some of my favourite .NET tools have been updated to .NET 2.0:

I’m anxiously awaiting the next version TestDriven.NET, too. A beta of v2.0 is available for those who want to try it.
 
An interesting add-in for .NET Reflector is SQL 2005 Assembly Browser by Denis Bauer. It allows you to browse .NET assemblies stored in SQL Server 2005. This is something I’m definitely going to investigate more thoroughly.
 
In related news, WSE 3.0 just RTMed!!! This is great news because WSE 3.0 will be wire-compatible with Indigo — uhm, I mean Windows Communication Foundation (WCF). This gives us a good migration story to Microsoft’s next generation distributed communication platform.
 
And somehow I also missed the fact that the coding superhero, Lutz Roeder, has a blog for a number of years, even if it is rather sparse. Subscribed.

Christian Weyer provides a nice overview of WS-* support in the current and upcoming Web Service technology stacks in the .NET world. He only includes out-of-the-box functionality, but many folks are providing additional transports, WS-* specs, etc. for WSE and WCF. As they say, your mileage may vary, but this is a great starting point when trying to figure out the WS-* smörgåsbord. (Yes, I had to look up that up on Meriam-Webster to be sure of the spelling.) :-)

I get this question relatively frequently:

“I need to send binary data in my SOAP message. What is the recommended way of doing this?”

(I’ll admit that I’m a bit late to the party on this one. Most of the information below is summarized from the referenced sources near the end of this post.)

You can always Base-64 encode the binary data, but this has a number of undesirable consequences including the encoding/decoding costs at the endpoints and a 33% size bloat on the wire. It does have the advantage that all the WS-* specs work with it.

So the next obvious question is how can I send the binary data as binary? This leads us to SOAP attachments. Unfortunately the SOAP attachments space is somewhat fragmented at the moment. The current options are:

  • SwA (SOAP with Attachments)
  • DIME (Direct Internet Message Encapsulation) (AKA WS-Attachments)
  • PASwA (Proposed Infoset Addendum to SOAP Messages with Attachments)
  • MTOM (Message Transmission Optimisation Mechanism)

All of these techniques send the attachments using MIME or a MIME-like mechanism. DIME adds record lengths to MIME for quick lookup of binary data. Unfortunately with SwA and DIME, the attachments are not part of the XML InfoSet, which means that you cannot apply the WS-* specs to them. (Probably most notable and serious is WS-Security. Using SwA or DIME, you can sign and/or encrypt parts of the SOAP message, but you cannot sign or encrypt the attachments. You can make guarentees that the message has not been tampered with, but you cannot make those same guarentees about the attachments.)

PASwA and MTOM solve this problem using an include element to incorporate the attachment into the XML Infoset. There seems to be general agreement that the way forward is MTOM. MTOM will be available with WSE 3.0 and Indigo. (WSE 3.0 is currently available as a CTP and Indigo is a Beta1 RC.)

So what should I do in the meantime? If you’re dealing with relatively few small binary attachments, Base-64 encoding seems to be the way to go. The extra 33% size and encoding/decoding costs probably won’t matter much to you.* On the plus side, you get to use all those snazzy WS-* specs. If you’re processing large numbers of messages and/or your attachments are large, the extra 33% size and encoding/decoding costs probably matter to you.* So you’ll have to use WSE 2.0 and DIME or roll your own SwA implementation (as Microsoft does not have an implemenation of SwA). Be aware that any WS-* goo that you apply will not work on the attachments. So don’t go sending images of bank statements via SwA or DIME!

* As with all things perf-related, measure, measure, measure. Don’t assume that Base-64 encoding is too slow for your situation and write a pile of extra encryption code for DIME attachments. Establish some performance criteria and measure against it. Then make an educated decision as to the solution architecture.

Here are some background articles that were good reads on the topic:

And don’t forget to catch John Bristowe‘s GrokTalk on MTOM in WSE 3.0:

Edit: Corrected wonky links and strange HTML formatting.