When you are invoking WebServices from your BizTalk Server 2004 orchestrations, you might need to ensure that two things happen correctly:
- Message delivery is retried if there's an error connecting to the WebService or if the service returns a SOAP fault
- Handle the case where the call fails after all retry attempts have been exhausted as part of your process
One way to accomplish this is by using Delivery Notifications to deal with the ACKs and NACKs from the messaging engine and the adapter. You can find some good information on this topic here, here, and here.
There's another option, however, that I discovered playing around and that is simpler to implement. This technique consists simply in wrapping the WebService call inside a scope with an Exception Handler. Here are the steps:
- Create a new Scope on the orchestration. There is no need to make it transactional, though it might be helpful in some cases to make it into a long-running transaction (atomic transactions won't work here because you can't put both the send and receive shapes for the service inside the same atomic scope).
- Add your Send and Receive shapes for the WebService call inside the new Scope you just created. Connect them to the corresponding operations of the port for the WebService.
- Right click on your BizTalk Project on Solution Explorer and select Add Reference. Add a reference to the System.Web.Services.dll assembly. We'll need this later to add the exception handler.
- Right-click on your scope and select Add New Exception Handler.
- Select the exception handler you just added and open the properties window. Configure the following properties:
Exception Object Type System.Web.Services.Protocols.SoapException
Exception Object Name ex (or whatever you prefer)
- Inside the exception handler, do whatever you need to do (including terminating the orchestration). From inside, you can access detailed information on the error in an Expression Shape by accesing ex.Details (an XmlNode).
One of the cool things about this method is that it leaves the retry logic completely to the Send Port configuration, so it leaves your orchestration pretty clean overall. Another interesting tidbit is that while you capture a SoapException, what BizTalk actually throws underneath is an exception of the derived XlangSoapException class (but that is fairly irrelevant for our needs).