Calling Web Service from BizTalk 2006 in a Messaging only Scenario (aka Content based Routing)

Published on : Jan 31, 2007

Category : BizTalk Server

Saravana

Author

In this article I’ll explain how you can call a Web Service which requires multiple arguments using a Custom pipeline and a custom pipeline component in a messaging-only scenario without using any Orchestration. biztalk web services   Normally, when there is a requirement to call a web service from BizTalk, people tend to take the easy route of calling it via an Orchestration. When we do a web reference inside the orchestration, Orchestration does quite a lot of work for us. It creates all the required schemas, it creates all the required multipart messages, which will be passed to the web service as argument. It makes our life easier. But I guess like me, some of you out there might need to call the web service without using Orchestration. As shown in the above figure. I’ve one request-response HTTP receive port, and one Solicit response SOAP send port, through this I’m going to call a web service, which expects multiple argument (including one complex type) and return the result back to the caller (HTTP Response). Here are the steps: The attached sample file contains all the required file, I’m just going to explain the key factors in this article.

1. Web Service Definition:

[WebMethod] public Person GetPersonInfo(Person person, string firstName, string secondName) { //Some processing return person; }

2. Create a general custom pipeline component to construct the multipart message required for the Web Service call

  At run time SOAP Adapter in the send port will map the Biztalk multipart IBaseMessage to the Web Service argument based on the partName of IBaseMessage and argument names of the Webservice. The key factor is how we are going to construct the multipart message in the format required by the SOAP Adapter to make the WebService call. In my previous article I explained how you can easily generate the required IBaseMessage with help of MIME message and MIME Decoder component. But when it comes to reality we don’t want to get into another data format like MIME. So, in this article we are going to create custom pipeline component which will construct the correct IBaseMessage required by the SOAP adapter based on the input message and some pipeline design time properties (for more detail on design time properties see my white paper ) . The custom pipeline component we are going to use has 2 design time properties FirstName and SecondName, which will be passed as parameters to the web service (See webservice definition from Step 1). We’ll pass the first webservice argument “Person” as the incoming message via HTTP receive port. The figure below show the custom design time properties configuration window within Biztalk Admin console. configuring pipelines The code below is the snippet from the custom pipeline component (two important methods Execute and CreateMessage). The Execute method below without the first line of code will be equivalent to a PassThru pipeline component with default Biztalk IBaseMessage. ############################################################# public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg) { IBaseMessage msg = CreateMessage(inmsg.BodyPart.GetOriginalDataStream(), pc.GetMessageFactory(),inmsg.Context); return msg; } ############################################################# IBaseMessage CreateMessage(Stream s, IBaseMessageFactory msgFactory, IBaseMessageContext context) { IBaseMessage msg = msgFactory.CreateMessage(); IBaseMessagePart part = msgFactory.CreateMessagePart(); part.Data = s; msg.AddPart(“Person“, part, true); msg.Context = context; //1st Part IBaseMessagePart partFirstName = msgFactory.CreateMessagePart(); byte[] firstPart = System.Text.Encoding.UTF8.GetBytes(string.Format(“<string>{0}</string>“, _firstName)); partFirstName.Data = new MemoryStream(firstPart); partFirstName.Charset = “utf-8” partFirstName.ContentType = “text/xml” msg.AddPart(“firstName“, partFirstName, false); //2nd Part IBaseMessagePart partSecondName = msgFactory.CreateMessagePart(); byte[] secondPart = System.Text.Encoding.UTF8.GetBytes(string.Format(“<string>{0}</string>”, _secondName)); partSecondName.Data = new MemoryStream(secondPart); partSecondName.Charset = “utf-8” partSecondName.ContentType = “text/xml” msg.AddPart(“secondName“, partSecondName, false); return msg; } ############################################################# Our user defined function CreateMessage will create the required BizTalk IBaseMessage as shown in the below figure BizTalk IBase Message In the above code snippet, the important things to note are highlighted in RED. The incoming message (“Person”) will go as the first part (BodyPart) of the IBaseMessage with the name “Person”, and then we added two more addional parts “firstName” and “secondName” to the IBaseMessage with correct partNames inline with the web service arguments. The other important thing to note is how the basic data types gets serialized. In our example we got “<string>{0}</string>” as value for firstName and secondName, because they are of type string. If for example you got int as your argument then you need to create the part in the format <int>5</int>. NOTE: See the web service signature defined in Step 1 for comparison

3. Create a Custom Receive Pipeline using the custom pipeline component

Create a new Biztalk Receive Pipeline and place the custom pipeline component we created in the “Decode” stage of the pipeline.

4. Configure the ports

As shown in our design diagram at the beginning we need 2 ports to send and receive the message, the attached sample file got a binding file, this section is just for explanation, doesn’t explain in detail how to configure the ports. Make sure the URL are correct, both on Receive and Send side after importing the binding. You need to configure IIS as well to receive messages via HTTP, follow the link to configure IIS for HTTP receive  http://msdn2.microsoft.com/en-us/library/aa559072.aspx.

Two-Way HTTP Receive Port:

Two-Way HTTP Receive Port

Solicit-Response SOAP Send Port:

We used the .NET Proxy class on our SOAP port to make the call. soap transport properties Filter Condition on the Send Port send port properties

5. Post a Message.

I used WFetch to post the message to BizTalk. You can see on the result pane the request message is posted and you got the response back from the web service synchronously on a two way connection. WFetch for BizTalk Messages

Troubleshooting:

Some of the common exceptions you’ll see while calling a webservice via SOAP adapter is shown below (from HAT and eventviewer) 1. “Failed to retrieve the message part for parameter “firstName”.2. “Failed to serialize the message part “firstName” into the type “String” using namespace “”. Please ensure that the message part stream is created properly.” The reason for the first error message is due to wrongly named IBaseMessage partName. Read Section 2 carefully to overcome this error. The reason for the second error message is mainly due to some problem with serializing the IBaseMessage parts to the correct web service arguments. Best approach to overcome this error will be to build a .net console/windows application, add a web reference to the webservice and try to serialize each argument to the corresponding type. For example for this example you can try the following FileStream fs = new FileStream(@”C:Documents and SettingsSaravanaKDesktopFailedMessages_Person.out“,FileMode.Open,FileAccess.Read); XmlSerializer serialise = new XmlSerializer(typeof(LH.WebReference.Person)); LH.WebReference.Person per = (LH.WebReference.Person)serialise.Deserialize(fs); fs.Close(); fs = new FileStream(@”C:Documents and SettingsSaravanaKDesktopFailedMessages_secondName.out“,FileMode.Open,FileAccess.Read); serialise = new XmlSerializer(typeof(string)); string s2 = (string)serialise.Deserialize(fs); fs.Close(); The files “_Person.out” and “_secondName.out” are saved from HAT tool. See the exception detail and fix the issue, it will be some namespace issue or data issue. DOWNLOAD SAMPLE Read the readme.txt file inside to configure it. Will take approximately 5-20 minutes based on your BizTalk knowledge level.

Related Post

In one of my previous post I explained how to call a web service that has more than one argument using a MIME message in a Content based routing(messaging only) scenario. Nandri! Saravana Kumar