BizTalk Custom Pipeline Backup incoming file

11.01.2021

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 next:

  • connstring: Connection string for connect the pipeline to external DB
  • table: table name where is configurate the folder lists where create the input backup
  • fieldFilePath: column name where get the backup folder
  • fieldKey: column name where is put the key where extract the right value (is the column name in WHERE condition)
  • valueKey: the value where make 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 next 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 for to reach the DB that contain tblConfiguration
  • table: tblConfiguration
  • fieldFilePath: filePathName
  • fieldKey: keyName
  • valueKey: key1

Next the code:

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>

/// 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>Configuration property bag</param>

/// <param>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>Configuration property bag</param>

/// <param>not used</param>

/// <param>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>Property bag</param>

/// <param>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>Property bag.</param>

/// <param>Name of property.</param>

/// <param>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>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>Pipeline context</param>

/// <param>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;


//Logic here


}

}