A question on the public BizTalk newsgroups brought the question of how to add arbitrary
binary message parts to a multi-part message in an orchestration and have them be
correctly processed by the MIME encoding component (or the SMTP adapter) in BizTalk
2006. By this I mean arbitrary parts (such as the contents of a bynary file) without
having it declared as part of the multi-part message type itself.

The first thing the poster turned to was to create a custom .NET component that received
the message as an argument and then called AddPart() on it passing a byte[] array
as an argument. Unfortunately, this causes the message part to be encoded by BizTalk
as an XML document with a single root node “<base64Binary>” which contains the
entire array as a base64 encoded string. Not quite what we wanted.

After looking around for a bit, I found a way to get around this by taking advantage
of the IStreamFactory interface: By providing a very simple implementation of this
interface, and creating the message part on top of that, we can get around this issue.
Here’s some sample code illustrating the concept:

public class BinaryStreamFactory : RefCountedBase,

   IRefCountedStreamFactory

{

   private Stream _stream;

 

   public BinaryStreamFactory(Stream stream)

   {

      if (
stream ==
null )

         throw new ArgumentNullException(“stream”);

      if (
stream.Position != 0 )

      {

         stream.Position
= 0;

      }

      _stream
= stream;

   }

 

   public Stream CreateStream()

   {

      return _stream;

   }

 

   public override void Dispose()

   {

      _stream.Dispose();

   }

 

} //
class BinaryStreamFactory

 

First we need an implementation of IStreamFactory. In this case, we have a fairly
simple implementation that just returns the stream we pass in the constructor. Notice
also that we also implement it as a RefCounted object (something that BizTalk also
looks for an allows us to ensure we know when to close the stream) using the helper
RefCountedBase base class.

Now all we need is to add the part by using this BinaryStreamFactory class:

public static void AttachStream(XLANGMessage message, string partName, Stream stream)

{

   if (
message ==
null )

      throw new ArgumentNullException(“message”);

   if (
partName ==
null )

      throw new ArgumentNullException(“partName”);

   if (
stream ==
null )

      throw new ArgumentNullException(“stream”);

 

   IStreamFactory factory
=
new BinaryStreamFactory(stream);

   message.AddPart(factory,
partName);

 

   //

   //
set the Filename property so that it

   //
gets correctly recognized in the mail

   //
reader app when it is received as an attachment

   //

   XLANGPart part
= message[partName];

   part.SetPartProperty(typeof(MIME.FileName),
partName);

}

I built a simple, yet complete example of how to use it, which can be downloaded from here.

One thing to note, however, is that if you are using the SMTP adapter in BizTalk
2006, it already has some features that might make this whole process easier using
the SMTP.Attachments context property. My friend Carlos had an example of this here.