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.

BTSWCFFault

A few things to keep in mind if you decide to try this:

  1. 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).
  2. 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.
  3. 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!

technorati BizTalk
Server 2006 R2, WCF, Web
Services