BizTalk 2006 SOAP Adapter (Web Service call) in Messaging Only Scenario

Published on : Dec 20, 2006

Category : BizTalk Server



Web Services support in BizTalk is not a new topic, it’s already mentioned heavily in few of the famous blogs like Darren Jefford , Aaron Skonnard, Biztalk Server Team Blog etc In this entry I’ll explain how you can use the out of the box SOAP adapter to call a web service in a messaging only scenario (aka Content based routing),  BizTalk 2004 SOAP adapter didn’t have this functionality, we need to use orchestrations along with SOAP adapters to call a Web Service. There is a MSDN sample called “Consuming Web Services (BizTalk Server Sample)” found under Samples, which show cases SOAP adapters messaging only capability, but it fails to explain in detail how its archived. The below figure shows the biztalk solution we are going to implement in this blog post. SOAP Adapter Messaging-only scenario

1. Web Service Definition:

For this sample we’ll define a simple web service with 2 web methods (sample download contains full implementation)
  1. ProductInfo GetProductInfo (CustomerInfo customer)
  2. ProductInfo GetProductInfoByAccountNumber (CustomerInfo customer, int accountNumber)
The below class diagram explains the custom in and out parameter (CustomerInfo and ProductInfo) data structure. web service definition

2. Create .NET Web Service Proxy Class:

Create a new Class Library project within Visual Studio, and Add Web Reference to the web service we created in Step 1. If you are using the sample application the url will be http://localhost:11258/SOAPMessagingOnly.WebService/CustomerProcessing.asmx We don’t need to add any custom coding to the proxy class, build the solution and deploy the assembly in GAC (you need to add strong name key to solution to do it).

3. Create Ports in Biztalk:

For this demonstration we are going to create 3 ports in BizTalk.
  1. MSG_File_Receive- File Receive
    1. Name : MSG_File_Receive
    2. Adapter: FILE
    3. Direction: One-Way
    4. Receive Pipeline: PassThru
    5. URI: <<Folder location where you are going to drop the file>>
  2. MSG_File_Send – File Send
    1. Name : MSG_File_Send 
    2. Adapter: FILE
    3. Direction: One-Way
    4. Send Pipeline: PassThru
    5. Filter: BTS.SPName = WS_SOAP_Send
    6. URI: <<Folder location where you want the web service response messages>>
  3. WS_SOAP_Send – SOAP Send
    1. Name : WS_SOAP_Send
    2. Adapter: SOAP
    3. Direction: Solicit-Response
    4. Receive Pipeline: PassThru
    5. Send Pipeline: PassThru
    6. Filter: BTS.ReceivePortName=MSG_File_Receive
    7. On the SOAP Adapter Config Screen Set:
Web Service URL: http://localhost:11258/SOAPMessagingOnly.WebService/CustomerProcessing.asmx Assembly Name: Pick the .dll of the web service proxy we created in step 2. Type Name: Fully Qualified name of CustomerProcessing Method Name: GetProductInfo (Once after creating all the ports, enlist and start the send ports and enable Receive Location.)

Key things to Note:

  • We didn’t deploy any schemas into Biztalk
  • All the pipeline are “PassThru” in our settings.
  • Messages are routed (Filter Conditions) purely based on promoted properties, in our case just port names.

4. Drop the Sample Message in the Receive Location Folder:

This is one of the confusing bit, if you browse to the asmx page in Internet explorer and see the request message for GetProductInfo Web method, the SOAP:Body element will have the XML content as shown below.   <GetProductInfo xmlns=””> <CustomerInfo xmlns=””> <CustomerID>string</CustomerID> </CustomerInfo> </GetProductInfo>   People often try to post the whole message to the SOAP adapter, thinking it will be transmitted as it’s. But the reality is Biztalk will submit the IBaseMessage (Multipart message) to the SOAP Adapter, then the SOAP adapter will pick up the part inside the IBaseMessage and assign it to the web service argument based on the content-id of the part. If we try to pass the whole message, then there will be a type mismatch. So all we need to pass is   <CustomerInfo xmlns=””> <CustomerID>string</CustomerID> </CustomerInfo>

Interesting Exception message:

Ok, just a quick quiz, can you suggest me some solution based on the following exception. The messaging engine was unable to resubmit a message for send port “WS_SOAP_Send” with URL http://localhost:11258/SOAPMessagingOnly.WebService/CustomerProcessing.asmx. Details:”Cannot access a disposed object. Object name: ‘CEventingReadStream’.”. I tried googling it, couldn’t find any search results. After a bit of experiment found out, its the problem with the namespace I specified in the sample message. Its one of the bizarre error messages I came across. You can replicate this exception by pasting the sample file “Namespace Error Customer.xml” found under MSG_SAMLES (from the download) folder in the receive location folder.  

So what happened to the second Web Method with 2 arguments?

As explained in step 4. I need to construct a Multipart message with two parts, first part will contain “customer” argument and the second part will have “accountNumber” argument. It’s still achievable by the traditional orchestration approach. In part 2 of the article I’ll explain in detail one of the approaches I took to solve this problem in a messaging only scenario without Orchestration. Download the sample here and follow the steps below.
  1. Create a folder called BTSSample under C: and extract all the files.
  2. Open the solution in Visual Studio, build it, copy the proxy client dll to GAC, and view CustomerProcessing.asmx in the browser, this will kick off ASP .NET web server with port 11258.
  3. Create a Biztalk 2006 Application called SOAPMessagingOnly and import the binding file binding.xml.
  4. Drop the sample file (placed inside MSG_SAMPLES folder) into the folder MSG_IN.
Nandri! Saravana