I wanted to catch a WCF fault. A quick search gave many hits about catching un-typed WCF faults for example http://geekswithblogs.net/paulp/archive/2008/06/23/123096.aspx and http://blogs.msdn.com/paolos/archive/2009/05/22/how-to-throw-typed-fault-exceptions-from-orchestrations-published-as-wcf-services.aspx. There is also an SDK example referenced in the blog by Paul Petrov. This blog describes how to catch a standard fault instead of an un-typed fault because I did not find any examples of this simpler case. I have recorded this here because it was not obvious to me from the examples above how to do it.
The web service that i was working with did not return a custom fault just a standard fault. I decided to follow the same general pattern given in the articles above but instead of creating my own custom exception schema I referenced http://schemas.xmlsoap.org/soap/envelope/ from the BTS system schemas (BTS.soap_envelope_1__1.Fault). Thus there is one less step than the Petrov’s pattern i.e.
- Create a new multi-part message type CalculatePremium_WCFFault that has part of type BTS.soap_envelope_1__1.Fault.
- Add to my CalculatePremiumPortType operation a new GenericWCFFault fault of type BTS.soap_envelope_1__1.Fault.
- Add an exception handler CatchGenericWCFFault for this new fault
Now I tried following the SDK example and modified the Inbound BizTalk message body area on the send port to my web service, doing the following:
a. Select Path–content located by body path option.
b. In the Body path expression field, enter /*[local-name()=’Fault’]/*[local-name()=’Detail’]/* | /*[local-name()=’PremiumResponse’].
c. From the Node encoding drop-down list, select Xml.
I also made sure that the Propagate fault message option is selected in the Error handling area. This did not work and I got an error probably because I did not get the body path expression correct.
To my surprise when I switched back and selected the default Body under body path option the WCF fault was caught and processed correctly. Now all is clear. I don’t have to use an XPath expression on the send port configuration because the general SOAP fault schema is known to the receive pipeline. The fault was copied in the Copy Errors and Exceptions shape using the following code
//Assign variables for WCF Fault where wcfFault is the exception of type PremiumCalcWebServiceLink[MyNameSpace.CalculatePremiumPortType].Operation_1.GenericWCFFault
wcfFaultStringXDoc = wcfFault.faultString;
sErrorMsg = wcfFaultStringXDoc.OuterXml;
In summary I can now catch all unhandled exceptions from my external web service.