BizTalk Server 2013: Processing Large Size Message "Bypass message through messagebox"

Introduction

This article intends to demonstrate the step-by-step procedure required to process large files and bypass Biztalk message box.

Scenario

A compressed message Zipped Archive will be received of size greater than 1.6 GB and we will uncompressed those files and send bypass message to message box containing  file path and file name.

Solution

There is no way to deal with large file size in BizTalk and if we try to pass large message through BizTalk, the MessageBox can go into inconsistent state . It can cause failure of further message flow.
In this article I would try to develop a solution to deal with similar scenarios where an end user wants to take advantage of BizTalk while trying to process large message.

  1. Input analysis
  2. Developing Custom bypass Message Box Component(UnzipMessageDisassembler)
  3. Developing Custom Pipeline(ZipReceivePipeline)
  4. Configuring the application
  5. Testing and Output analysis

Input Analysis

The sample input message here is a Zipped Archive file which has to be uncompressed before being processed.

Developing Custom Bypass Component at Decoder stage

 

1. Create a C#  class library project which will hold the custom decode component, the purpose of this component is to bypass the large message and a custom Bypass message to message box which is being used with Orchestration .

  1. To develop custom decode Component, four interfaces are to be implemented - IBaseComponent, IComponentUI, IPersistPropertyBag and IDisassemblerComponent. And this Interfaces have Methods and Properties defined which should be implemented. 
    **
    **3. In order to implement these interfaces, we need to use namespaces "Microsoft.BizTalk.Message.Interop","Microsoft.BizTalk.Component.Interop" which belong to "Microsoft.BizTalk.Pipeline.dll" assembly, can be found at C:\Program Files\Microsoft BizTalk Server 2013\Microsoft.BizTalk.Pipeline.dll
    **
    **4. Right click the project and add a reference to Microsoft.BizTalk.Pipeline.dll
using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Resources;
using System.Reflection;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Component;
using Microsoft.BizTalk.Messaging;
using System.Xml;

4. To indicate that the component is a custom pipeline component and can only be used in Decoder stage, couple of attributes are added to the class. And Unique Identity is to be added.
**
**

[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
    [System.Runtime.InteropServices.Guid("b77532b9-5a1b-4207-a257-174eae5cf330")]
    [ComponentCategory(CategoryTypes.CATID_Decoder)]

5. It’s the Decode method of IDecodeComponent Interface where the logic of Bypassing message box and creating bypass message is implemented**.**
**

**

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage inmsg)
{
 
 
    if (inmsg.BodyPart != null)
    {
        
        Stream originalStream = inmsg.BodyPart.GetOriginalDataStream();
        string interchangeId = inmsg.Context.Read("InterchangeID", "http://schemas.microsoft.com/BizTalk/2003/system-properties").ToString();
        Guid interchangeGuid = new Guid(interchangeId);
        string FilePath = interchangeGuid.ToString("B") + "_" + inmsg.BodyPart.PartID.ToString("B") + "_" + inmsg.BodyPartName + ".zip";
 
        FileStream fs = new FileStream(FilePath, FileMode.Create);
 
        // Write message to disk
        byte[] buffer = new byte[1];
        int bytesRead = originalStream.Read(buffer, 0, buffer.Length);
        while (bytesRead != 0)
        {
            fs.Flush();
            fs.Write(buffer, 0, buffer.Length);
            bytesRead = originalStream.Read(buffer, 0, buffer.Length);
        }
        fs.Flush();
        fs.Close();
 
        // Create a small xml file
        string xmlInfo = "<ns0:Bypassmessage xmlns:ns0='http://testbypassmessage/ Sample'><filepro>filepr01</filePro><SourceFileName>SourceFileName_0</SourceFileName></ns0:Bypassmessage";
        byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(xmlInfo);
        MemoryStream ms = new MemoryStream(byteArray);
        inmsg.BodyPart.Data = ms;
    }
    return inmsg;
}
  1. The complete code is as below:
namespace BizTalk.BypassMessageBox
{
    using System;
    using System.IO;
    using System.Text;
    using System.Drawing;
    using System.Resources;
    using System.Reflection;
    using System.Diagnostics;
    using System.Collections;
    using System.ComponentModel;
    using Microsoft.BizTalk.Message.Interop;
    using Microsoft.BizTalk.Component.Interop;
    using Microsoft.BizTalk.Component;
    using Microsoft.BizTalk.Messaging;
    using System.Xml;
  
     
    [ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
    [System.Runtime.InteropServices.Guid("b77532b9-5a1b-4207-a257-174eae5cf330")]
    [ComponentCategory(CategoryTypes.CATID_Decoder)]
    public class CongeraReceive : Microsoft.BizTalk.Component.Interop.IComponent, IBaseComponent, IPersistPropertyBag, IComponentUI
    {
 
        #region IBaseComponent
        private const string _Description = "Pipeline component for BypassMessageBox";
        private const string _Name = "BypassMessageBox";
        private const string _Version = "1.0.0.0";
 
        public string Description
        {
            get { return _Description; }
        }
        public string Name
        {
            get { return _Name; }
        }
        public string Version
        {
            get { return _Version; }
        }
        #endregion
 
        #region IComponentUI
        private IntPtr _icon = new IntPtr();
        public IntPtr Icon
        {
            get { return _icon; }
        }
        public System.Collections.IEnumerator Validate(object projectSystem)
        {
            return null;
        }
        #endregion
 
        #region IComponent
        public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage inmsg)
        {
 
 
            if (inmsg.BodyPart != null)
            {
                
                Stream originalStream = inmsg.BodyPart.GetOriginalDataStream();
                string interchangeId = inmsg.Context.Read("InterchangeID", "http://schemas.microsoft.com/BizTalk/2003/system-properties").ToString();
                Guid interchangeGuid = new Guid(interchangeId);
                string FilePath = interchangeGuid.ToString("B") + "_" + inmsg.BodyPart.PartID.ToString("B") + "_" + inmsg.BodyPartName + ".zip";
 
                FileStream fs = new FileStream(congeraFilePath, FileMode.Create);
 
                // Write message to disk
                byte[] buffer = new byte[1];
                int bytesRead = originalStream.Read(buffer, 0, buffer.Length);
                while (bytesRead != 0)
                {
                    fs.Flush();
                    fs.Write(buffer, 0, buffer.Length);
                    bytesRead = originalStream.Read(buffer, 0, buffer.Length);
                }
                fs.Flush();
                fs.Close();
 
                // Create a small xml file
                string xmlInfo = "<ns0:BypassMessageBox xmlns:ns0='http://bypassmessagebox/'><filepro>filepro1</filepro><SourceFileName>SourceFileName_0</SourceFileName></ns0:BypassMessageBox>";
                byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(xmlInfo);
                MemoryStream ms = new MemoryStream(byteArray);
                inmsg.BodyPart.Data = ms;
            }
            return inmsg;
        }
 
        #endregion
 
        #region IPersistPropertyBag
        private string _largeFileLocation;
        private int _thresholdSize;
 
        public string LargeFileLocation
        {
            get { return _largeFileLocation; }
            set { _largeFileLocation = value; }
        }
 
        public int ThresholdSize
        {
            get { return _thresholdSize; }
            set { _thresholdSize = value; }
        }
 
        public void GetClassID(out Guid classID)
        {
            classID = new Guid("53fd04d5-8337-42c2-99eb-32ac96d1105a");
        }
        public void InitNew()
        {
        }
        public void Load(IPropertyBag propertyBag, int errorLog)
        {
            object val1 = null;
            object val2 = null;
            try
            {
                propertyBag.Read("LargeFileLocation", out val1, 0);
                propertyBag.Read("ThresholdSize", out val2, 0);
            }
            catch (ArgumentException)
            {
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Error reading PropertyBag: " + ex.Message);
            }
            if (val1 != null)
                _largeFileLocation = (string)val1;
 
            if (val2 != null)
                _thresholdSize = (int)val2;
 
        }
        public void Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties)
        {
            object val1 = (object)_largeFileLocation;
            propertyBag.Write("LargeFileLocation", ref val1);
 
            object val2 = (object)_thresholdSize;
            propertyBag.Write("ThresholdSize", ref val2);
        }
        #endregion
    }
}

See Also

Another important place to find a huge amount of BizTalk related articles is the TechNet Wiki itself. The best entry point is BizTalk Server Resources on the TechNet Wiki.