Dealing with web services returning byte[] in BizTalk

Posted at: 11/5/2008 at 11:51 AM by saravana

Recently I saw some postings in the BizTalk newsgroup asking how we can handle web service operation that returns a byte[]. Even though it’s a trivial task, you need to be aware of certain things.

Below is my simple web service operation, which returns a byte[]. For simplicity, I just got this one operation which can return either a simple string, or some form of xml or some binary data .

clip_image002[1]

When you invoke your web service from Internet explorer, you’ll get the result something similar to the one shown below (This is the data you’ll get inside your orchestration as well).

<base64Binary xmlns="http://9b957340-adba-3234-91ea-46a5c9bff530/">dGhpcyBpcyBhIHRlc3Q=</base64Binary> 

Adding a web reference to the above service inside your orchestration project, will create a schema (Reference.xsd) with a single root element called "base64Binary" of xsd type "base64Binary" as shown below.

<xs:element name="base64Binary" nillable="true" type="xs:base64Binary" />

Orchestration:

The sample orchestration used for this demonstration is shown below:

clip_image004[1]

Scenario #1: byte[] contains some string data:

There are couple of ways you can deal with this scenario.

Option 1: Using map:

In this approach, you can use the scripting functoid and write an inline script as shown below. It important you use the correct encoding methods to parse the string. In this case it was encoded using UTF8 on the web service.

   1: public string GetString(string param1) 
   2: { 
   3: byte[] b = System.Convert.FromBase64String(param1); 
   4: return System.Text.Encoding.UTF8.GetString(b); 
   5: } 

clip_image006[1]

Option 2: Using xpath function and helper class:

In this approach we use the orchestrations xpath function to get hold of the binary base64 data as shown below and pass it to a helper method to get the corresponding data.

   1: base64Data = xpath(WS_GetBinary_RESP.GetBinaryResult, "string(/*[local-name()='base64Binary' and namespace-uri()='http://9b957340-adba-3234-91ea-46a5c9bff530/'])"); 
   2: text = Helper.Utility.GetString(base64Data); 

base64Data is a variable of type string

Helper method:

clip_image008[1]

Scenario #2: byte[] contains some xml data:

This scenario is similar to our previous simple text scenario, only difference here is we modified our helper method to parse and load the xml data into XmlDocument object as shown below.

Helper method:

clip_image010[1]

Scenario #3: byte[] contains some binary data:

Dealing with binary data is bit interesting. You need to understand some of the basic points here.

  1. The parts in the multi-part orchestration message can hold any data; there is no restriction to put only xml data in the message parts.
  2. If you define a message variable of type System.Xml.XmlDocument, you can assign an XLANGMessage, which in turn can be a multi-part message with or without xml data in any of the parts. As long as you are not trying to validate it or use any xpath syntax on it, there won’t be any errors.
  3. When constructing an XLANGMessage with a stream, the stream type must either implement IStreamFactory or be a MemoryStream (http://msdn.microsoft.com/en-us/library/aa995576.aspx ).

In this approach we are going to make use of all the above mentioned points. First in our helper dll, we’ll create a class called CustomStreamFactory which inherits from IStreamFactory and implement the interface method CreateStream as shown below.

clip_image012[1]

As you can see its a very simple implementation, the class constructor take a byte[] and assign it to a member variable. CreateStream interface method creates and returns a new MemoryStream using the data in member variable.

Helper method:

We create a helper method as shown below to populate the content of the first part with our binary data using XLANGPart, LoadFrom method:

clip_image014[1]

The syntax here is bit strange, we are not passing the XLANGMessage as ref or out parameter. But that’s how its been documented and it works!!

Now within the orchestration expression shape you can assign the message as shown below:

construct MSG_XMLDOC

{

MSG_XMLDOC = new System.Xml.XmlDocument();

Helper.Utility.GetBinary(MSG_XMLDOC,base64Data);

}

If you send the above message(MSG_XMLDOC) to a file drop location with .jpg extension, you will see the image returned from the web service.

TIP: The above syntax in an expression shape is equivalent to putting the code inside a message assignment shape within a Construct shape.

In fact you could have just used our scenario 3 to handle simple text(scenario 1) and xml data (scenario 2).

Nandri!

Saravana

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: | |  Categories: BizTalk General
Actions: Email this article Email | Kick it! | DZone it! | Save to del.icio.us | Technorati Links
Post Information: Permanent LinkPermalink | CommentsComments(7) | Comments RSS

Comments

Wednesday, November 05, 2008 1:41 PM
Mehmet AYDIN
Thank you very much,
this was very helpful for me,
thanks again.
best regards.
Friday, November 07, 2008 8:30 PM
Bryan us
Bryan
Saravana,

This is very helpful.. thanks for posting.. 1 question though is how would you do the reverse. I have a file (could be txt, xls, pdf) that is dropped and Recieved as a System.Xml.XmlDocument in the Orchestraton. I need to pass that file to a Webservice that is expecting byte[] (the Reference.xsd says base64Binary)

Thanks again.
Bryan
Monday, November 10, 2008 10:15 AM
Saravana Kumar
This post from Richard Seroter will help you do that blogs.msdn.com/.../673921.aspx

Regards,
Saravana
Monday, November 10, 2008 1:39 PM
Bryan us
Bryan
Very much appreciated.. Thank you Saravana.

Bryan

Monday, November 10, 2008 9:47 PM
Bryan us
Bryan
Saravana,

I have another question for you.. My orchestration takes in a file dropped from SSRS to a file location on disk, the file could be a xls or pdf or someother file. which i then store as a system.xml.xmldocument. It is that document that i need to convert to pass into a webservice method which is defined as a base64binary. Along with other parameters. My question is how do i convert the system.xml.xmldocument to be able to be passed to the helper method? I looked at the link you provided above, but I feel like I'm missing a step from where i get this xmlDocument to be able to be passed to the helper functions.

Thanks again for all your invaluable insight.
Bryan
Thursday, December 04, 2008 2:35 AM
Busby SEO Test
that's good to you!but I'm also thinking about this!!
Friday, December 05, 2008 4:01 PM
BizTalkNewBie us
BizTalkNewBie
Saravana,

great post. My comment is not so much related to the content, however ... I like to print blogs like this so I can take them along with me to read during lunch breaks, at red lights, etc. However, when I went to print this blog (luckily I did a print preview first; note, I set the page to landscape because in portrait the whole page didn't fit), after the first page, all the rest were blank. Is there anything I need to do on my end so that I can print the entire blog?

Thanks in advance for your patience with such a simple request,

BizTalkNewBie

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading