BizTalk Server has some pretty strong facilities for making a "best effort" at ensuring message delivery, by using the automatic retry facilities available to BizTalk Send Ports.
This functionality is available when calling Web Services as well either with the WCF or SOAP adapters, and it's very useful. However, it's not always enough by itself.
One such scenario comes up when the Web Service you're calling does not return SOAP Faults when it fails, but instead returns some kind of status/result indicator as part of a normal response message. In that case, the SOAP/WCF adapter can't tell on its own that the service call failed and retry it as necessary.
There are a few ways you can deal with this.
For example, you can handle retries manually from an orchestration, using a Loop shape to call the service, check the result and retry the call as necessary. It's not complex (though a bit cumbersome) and in many scenarios works very well.
Unfortunately, this isn't an option if you are in a messaging-only scenario, or have complex routing rules leading to the service invocation (common with direct-binding scenarios).
One possible workaround for this if you're using the WCF Adapter in R2 that I've been experimenting lately with is to use the WCF-Custom adapter and configure a custom Endpoint Behavior that adds an IClientMessageInspector implementation that checks the response message and transforms it to a fault if it indicates.
A few things to keep in mind if you decide to try this:
- For your behavior to be listed on the BizTalk Administration console, you'll need to implement a BehaviorExtensionElement for it, deploy it to the GAC and register it in machine.config (or at least this was the way I did it).
- Inside your
IClientMessageInspector.AfterReceiveReply()implementation, you might need to create a buffered copy of the message and return a new Message instance built from it to the WCF Adapter runtime; otherwise BizTalk might not be able read the message because you've already consumed it and it will be in the closed state by then.
- Make sure you leave the "Propagate Fault Message" option unchecked; otherwise your fault will just be submitted to BizTalk as a regular message and won't cause the send port to retry the call.
My friend Carlos suggested that another way to deal with this issue (particularly if you're not using the WCF adapter) might be by building a custom pipeline component and using it in a receive pipeline configured in the Send Port. The component would then read the response from the Web Service and throw an exception to force a failure during the response processing if necessary, thus causing the entire exchange to fail. I haven't tried this myself, but sounds like another useful idea!