Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#4.0

BizTalk Receive Custom Pipeline Backup Incoming Message

0.00/5 (No votes)
12 Jan 2021CPOL1 min read 3.1K   17  
Custom Pipeline that backs up incoming message to folders retrieve from external DB
This pipeline creates a backup input message to retrieve the property backup from the external DB. All these properties are configurable like pipeline's parameters.

Introduction

One of the most annoying problems in an integration environment is when you receive a file that does not check the input scheme applied to the receiving port. This causes the typical unacknowledged message exception and putting the message on hold. From here, we need to analyze the problem in the BizTalk Administration Console.
Through this custom pipeline, it is possible to have a copy of the input message in one or more backup folders before it is subjected to the validation process, thus allowing a simpler analysis of the structure. In this way, it's possible to generate an input copy in a lots directory folder, just configure a table in an external DB. The DB name, table name, column name, and key are configurable like properties in the pipeline.

The properties are as given below:

  • connstring: Connection string for connecting the pipeline to external DB
  • table: table name where the folder lists that create the input backup is configured
  • fieldFilePath: column name that gets the backup folder
  • fieldKey: column name in which the key that extracts the right value (is the column name in WHERE condition) is put
  • valueKey: the value that makes the filter

For example, if we have a table name tblConfiguration that contains a column with name filePathName and a column with name keyName with the following values:

  • filePathName: C:\Test\Backup\Input1;C:\Test\Backup\Input2;C:\Test\Backup\Input3
  • keyName: key1

The pipeline configuration will be:

  • connstring: the connection string to reach the DB that contains tblConfiguration
  • table: tblConfiguration
  • fieldFilePath: filePathName
  • fieldKey: keyName
  • valueKey: key1

Using the Code

C#
namespace EnL.Msg.Input.Pipeline.Utils
{
    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 Microsoft.BizTalk.Streaming;
    using System.Xml.Serialization;
    using System.Xml;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;

    [ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
    [System.Runtime.InteropServices.Guid("2a86d48b-a784-4475-8613-3497a3c23bc6")]
    [ComponentCategory(CategoryTypes.CATID_Any)]
    public class MsgUtils : Microsoft.BizTalk.Component.Interop.IComponent, 
                            IBaseComponent, IPersistPropertyBag, IComponentUI
    {
        #region Initiation
        
        private string _connString;
        private string _table;
        private string _fieldFilePath;
        private string _fieldkey;
        private string _valuekey;       
        
        #endregion

        #region Properties
        public string connString
        {
            get
            {
                return _connString;
            }
            set
            {
                _connString = value;
            }
        }

        public string table
        {
            get
            {
                return _table;
            }
            set
            {
                _table = value;
            }
        }

        public string fieldFilePath
        {
            get
            {
                return _fieldFilePath;
            }
            set
            {
                _fieldFilePath = value;
            }
        }

        public string fieldkey
        {
            get { return _fieldkey; }
            set { _fieldkey = value; }
        }

        public string valuekey
        {
            get { return _valuekey; }
            set { _valuekey = value; }
        }

        #endregion

        #region IBaseComponent members
        /// <summary>
        /// Name of the component
        /// </summary>
        [Browsable(false)]
        public string Name
        {
            get
            {
                return "EnL Message Input Utility";
            }
        }

        /// <summary>
        /// Version of the component
        /// </summary>
        [Browsable(false)]
        public string Version
        {
            get
            {
                return "1.0.0.0";
            }
        }

        /// <summary>
        /// Description of the component
        /// </summary>
        [Browsable(false)]
        public string Description
        {
            get
            {
                return "Create backup input file from configurable DB";    
            }
        }
        #endregion

        #region IPersistPropertyBag members
        /// <summary>
        /// Gets class ID of component for usage from unmanaged code.
        /// </summary>
        /// <param name="classid">
        /// Class ID of the component
        /// </param>
        public void GetClassID(out System.Guid classid)
        {
            classid = new System.Guid("2a86d48b-a784-4475-8613-3497a3c23bc6");
        }

        /// <summary>
        /// not implemented
        /// </summary>
        public void InitNew()
        {
        }

        /// <summary>
        /// Loads configuration properties for the component
        /// </summary>
        /// <param name="pb">Configuration property bag</param>
        /// <param name="errlog">Error status</param>
        public virtual void Load
        (Microsoft.BizTalk.Component.Interop.IPropertyBag pb, int errlog)
        {
            object val = null;
            val = this.ReadPropertyBag(pb, "connString");
            if ((val != null))
            {
                this._connString = ((string)(val));
            }
            val = this.ReadPropertyBag(pb, "table");
            if ((val != null))
            {
                this._table = ((string)(val));
            }
            val = this.ReadPropertyBag(pb, "fieldFilePath");
            if ((val != null))
            {
                this._fieldFilePath = ((string)(val));
            }
            val = this.ReadPropertyBag(pb, "fieldkey");
            if ((val != null))
            {
                this._fieldkey = ((string)(val));
            }
            val = this.ReadPropertyBag(pb, "valuekey");
            if ((val != null))
            {
                this._valuekey = ((string)(val));
            }
        }

        /// <summary>
        /// Saves the current component configuration into the property bag
        /// </summary>
        /// <param name="pb">Configuration property bag</param>
        /// <param name="fClearDirty">not used</param>
        /// <param name="fSaveAllProperties">not used</param>
        public virtual void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, 
                                 bool fClearDirty, bool fSaveAllProperties)
        {
            this.WritePropertyBag(pb, "connString", this.connString);
            this.WritePropertyBag(pb, "table", this.table);
            this.WritePropertyBag(pb, "fieldFilePath", this.fieldFilePath);
            this.WritePropertyBag(pb, "fieldkey", this.fieldkey);
            this.WritePropertyBag(pb, "valuekey", this.valuekey);
        }

        #region utility functionality
        /// <summary>
        /// Reads property value from property bag
        /// </summary>
        /// <param name="pb">Property bag</param>
        /// <param name="propName">Name of property</param>
        /// <returns>Value of the property</returns>
        public object ReadPropertyBag
               (Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName)
        {
            object val = null;
            try
            {
                pb.Read(propName, out val, 0);
            }
            catch (System.ArgumentException)
            {
                return val;
            }
            catch (System.Exception e)
            {
                throw new System.ApplicationException(e.Message);
            }
            return val;
        }

        /// <summary>
        /// Writes property values into a property bag.
        /// </summary>
        /// <param name="pb">Property bag.</param>
        /// <param name="propName">Name of property.</param>
        /// <param name="val">Value of property.</param>
        public void WritePropertyBag
          (Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName, object val)
        {
            try
            {
                pb.Write(propName, ref val);
            }
            catch (System.Exception e)
            {
                throw new System.ApplicationException(e.Message);
            }
        }
        #endregion
        #endregion

        #region IComponentUI members
        /// <summary>
        /// Component icon to use in BizTalk Editor
        /// </summary>
        [Browsable(false)]
        public IntPtr Icon
        {
            get
            {
                return new System.IntPtr();
            }
        }

        /// <summary>
        /// The Validate method is called by the BizTalk Editor during the build 
        /// of a BizTalk project.
        /// </summary>
        /// <param name="obj">An Object containing the configuration properties.</param>
        /// <returns>The IEnumerator enables the caller to enumerate through 
        /// a collection of strings containing error messages. 
        /// These error messages appear as compiler error messages. 
        /// To report successful property validation, the method should return 
        /// an empty enumerator.
        /// </returns>
        public System.Collections.IEnumerator Validate(object obj)
        {
            // example implementation:
            // ArrayList errorList = new ArrayList();
            // errorList.Add("This is a compiler error");
            // return errorList.GetEnumerator();
            return null;
        }
        #endregion

        #region IComponent members
        /// <summary>
        /// Implements IComponent.Execute method.
        /// </summary>
        /// <param name="pc">Pipeline context</param>
        /// <param name="inmsg">Input message</param>
        /// <returns>Original input message</returns>
        /// <remarks>
        /// IComponent.Execute method is used to initiate
        /// the processing of the message in this pipeline component.
        /// </remarks>
        public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute
               (Microsoft.BizTalk.Component.Interop.IPipelineContext pc, 
                Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)
        {
            System.Diagnostics.EventLog myEvt = new EventLog();
            myEvt.Source = "EnL Msg Pipeline";

            Stream dataStream = inmsg.BodyPart.Data;
            Stream dataStreamOut = inmsg.BodyPart.Data;
            IBaseMessageContext messageContext = inmsg.Context;
            string portName = messageContext.Read("ReceivePortName", 
              "http://schemas.microsoft.com/BizTalk/2003/system-properties").ToString();
            string fileName = messageContext.Read("ReceivedFileName", 
              "http://schemas.microsoft.com/BizTalk/2003/file-properties").ToString();
            FileInfo myFile = new FileInfo(fileName);
            fileName = myFile.Name;
            string msgInput = String.Empty;

            //Logic here
            try
            {      
                if (
                    connString != "" &&
                    table != "" &&
                    fieldFilePath != "" &&
                    fieldkey != "" &&
                    valuekey != ""
                   )
                {
                    using (StreamReader readerMsg = 
                           new StreamReader(inmsg.BodyPart.GetOriginalDataStream()))
                    {
                        msgInput = readerMsg.ReadToEnd();
                    }
                    CreateFileBackup(msgInput, connString, table, fieldFilePath, 
                                     fieldkey, valuekey, fileName);
                }                
            }
            catch (Exception ex)
            {
                myEvt.Source = "EnL Msg Pipeline";
                myEvt.WriteEntry("error: " + ex.Message, EventLogEntryType.Error);
            }

            byte[] outBytes = System.Text.Encoding.UTF8.GetBytes(msgInput);

            MemoryStream memStream = new MemoryStream();
            memStream.Write(outBytes, 0, outBytes.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            inmsg.BodyPart.Data = memStream;

            return inmsg;
        }
        #endregion

        public void CreateFileBackup(string msgInput, string connString, 
        string table, string columnResult, string columnKey, string key, string fileName)
        {
            SqlCommand cmd = new SqlCommand();
            SqlConnection conn = new SqlConnection(connString);
            cmd.Connection = conn;
            cmd.CommandText = "SELECT " + columnResult + " FROM " + table + 
                              " WHERE " + columnKey + "=@keyId";
            cmd.Parameters.AddWithValue("@keyId", key);

            string result = "";
            conn.Open();
            SqlDataReader dr = cmd.ExecuteReader();
            while (dr.Read())
            {
                result = dr[columnResult].ToString();
            }
            dr.Close();

            ((IDisposable)dr).Dispose();//always good idea to do proper cleanup

            string[] files = result.Split(';');
            foreach (var file in files)
            {
                CreateFile(msgInput, file, fileName);
            }
        }
        public void CreateFile(string msgInput, string filePath, string fileName)
        {
            string path = filePath + @"\" + fileName;
            using (FileStream fs = File.Create(path))
            {
                byte[] info = new UTF8Encoding(true).GetBytes(msgInput);
                fs.Write(info, 0, info.Length);
            }
        }
    }
}

History

  • 12th January, 2021: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)