Handling a Web-Service Null Response: The ‘CreateBodyPart’ Pipeline Component

Originally posted by Nick Heppleston at: http://www.modhul.com/2009/03/11/handling-a-web-service-null-response-the-createbodypart-pipeline-component/

Today I’m releasing a small component that addresses an interesting problem I’ve never come across before – a null response from a web-service.

The web-service in question is provided by a third-party and unfortunately cannot be changed. Their WSDL defines the root response element with a maxOccurs=1 and a minOccurs=0, which allows for a null response to be returned. So instead of a result element with no child nodes as I would expect (below in green):

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="..." xmlns:xsd="..." xmlns:xsi="...">
 <soapenv:Body>
  <GetPendingSalesOrdersResponse>
    <PendingSalesOrdersResult xmlns="..." />
  </GetPendingSalesOrdersResponse>
 </soapenv:Body>
</soapenv:Envelope>

we’re receiving an empty response (note the lack of an element between the <GetPendingSalesOrdersResponse> element):

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="..." xmlns:xsd="..." xmlns:xsi="...">
 <soapenv:Body>
  <GetPendingSalesOrdersResponse>
  </GetPendingSalesOrdersResponse>
 </soapenv:Body>
</soapenv:Envelope>

When the SOAP adapter receives this null response, it creates a message but neglects to create a body part – I presume this is because there is nothing to create it from. As a result, the message fails in both an XmlReceive and PassThruReceive pipeline; when using the PassThruReceive pipeline, the XLANG/s engine throws the following error when it tries to read the body part:

The XLANG/s message has no part at index ‘0’.  The total number of parts found in the message is ‘0’. If you expect a multipart message, check that the pipeline supports multipart messages such as MIME.

To address this problem, I’ve created a very simple receive pipeline component which lives on the receive side of the web-service solicit-response port and interrogates a message to determine whether it has a message body. If a message body is not present, it creates one based on the component properties (which mimic the expected – valid – response from the web-service) allowing the response message to be passed into the Message Box without issue. It a message body is present, it passes the message through unchanged.

The CreateBodyPart Pipeline Component

The component lives in the Decode stage of the receive pipeline and simply detects for the presence of a message body. If the body part is null, a new message part is created using the component properties BodyPartName and BodyPartContent and assigned as the body part of the message, before being passed onto the next stage of the pipeline. The BodyPartName and BodyPartContent properties specify the name of the body part and the Xml you want the part to contain – given that the content of the message is likely to be small-ish (i.e. <PendingSalesOrdersResult xmlns=”…” /> in the example above).

There are a few enhancements that I can envisage for this component already, including the ability to specify whether the part should be a body part – you might just want to create extra parts on the fly, not just a body part; and also the ability to specify the encoding and character set being used with your part content. However, I’ll leave these enhancements for a later day.

You can find binaries and source for the component at Codeplex: http://btscreatebdyprtcomp.codeplex.com/

As a final note, my client is currently running BizTalk 2006 (not R2) and we are running on the out-of-box SOAP adapter. Does anyone know whether this issue is a problem in the WCF-SOAP adapter or the WSE adapter?

Reblog this post [with Zemanta]