How to Develop BizTalk Custom Pipeline Components - Part1

Receive and send pipelines in BizTalk are used to perform a range of processing and operations on messages. They can –

1. Encrypt and decrypt messages

2. Sign and verify digitally signed messages

3. Validate message against schema

4. Deal with promoted properties used for content based routing

5. Disassemble or break single message into multiple

6. Wrap messages with header and footer

Pipelines contain stages and each stage can hold more than one pipeline component. Pipelines and pipeline components present out of box can do most of the tasks for you. But sometime specific message processing or massaging requirements encourage developers to develop custom pipeline components. Current series is focused on describing development of custom pipeline components.

There are multiple categories of pipeline components each doing specific job when employed on their predefined stages. These categories are –

Pipeline Components

Stages Employed


General Component

Decode, Encode, Pre-assemble, Resolve Party or Validate

Take one message process message and produce zero or one message

Disassemble Component


Split message, promote custom properties

Assemble Component


Used to wrap message with head or trailer or both

Probe Component

This is not an independent component. Any pipeline component can implement the IProbeMessage interface if it must support message probing functionality.

Enables the component to check the beginning part of the message

During development, each of these components implements particular interfaces and execute custom written job (code) on messages. I will walk through development of each of these components with sample code.

Developing General Pipeline Component

As stated earlier, pipeline components implement certain interfaces. General pipeline component implements following interfaces –

a. IBaseComponent Interface

b. IComponentUI Interface

c. IComponent Interface

d. IPersistPropertyBag (Optional. Required when pipeline design time properties are to be defined)

IBaseComponent Interface

All pipelines implement this interface. Interface provides members which can be implemented to provide information about pipeline.




Property. Used to specify small description about pipeline component. Description is visible on pipeline properties page at design time.


Property used to specify name of pipeline component. Name is visible on pipeline properties page at design time.


Property used to specify version (example of pipeline component. Visible on pipeline properties page at design time.

IComponentUI Interface

All pipeline components must implement this interface. Members of this interface provide design time support.




Property used to provide icon associated with pipeline component.


Method. This is called by pipeline designer before pipeline compilation to verify that all configuration properties are correctly set.

IComponent Interface

This is core interface. Member of this interface is implemented for specific message processing/massaging.




Method. Does specific processing/massaging in inbound message and produces output message to be forwarded to next stages of pipeline or message box.


Interface provides members which can be used to save and load pipeline design time properties with property bag. This interface is implemented only when pipeline’s design time properties are to be defined.




Method. Retrieves the component's globally unique identifying value.


Method. Initializes any objects needed by the component to use the persisted properties.


Method. Used to load property from property bag.


Method. Used to save property to property bag.

Enough theory. This is time for some coding.

Code Walk Though with Sample

I am going to create a sample general pipeline component. Scenario is very simple. Whenever, I receive a message, I want to change namespace of message in pipeline component. Namespace to be changed can be configured in design time property of pipeline.

If I get a message like following –

<Input xmlns:ns0="http://MyNamespace">




And if changed namespace property is set to http://MyNewNamespace , then output message (which goes to next stages of pipeline and message box) would become –

<Input xmlns:ns0="http://MyNewNamespace">




I am using VS 2005 for development.

1. Create a class library project say SampleGenPipelineComponent.proj. When project is created, rename Class1.cs to SampleGenComponent.cs.

2. Configure strong name key file in project property so that assembly can be signed.

3. Add following reference


References can be found in folder “C:\Program Files\Microsoft BizTalk Server 2006” depending on location of BTS installation.

4. Add following namespaces.

using System.Xml;

using System.IO;

using Microsoft.BizTalk.Message.Interop;

using Microsoft.BizTalk.Component.Interop;

5. Implement following interfaces-

IBaseComponent, IComponentUI, IComponent, IPersistPropertyBag

6. Add following attributes to pipeline component class


    [ComponentCategory(CategoryTypes.CATID_Decoder )]


public class SampleGenComponent :






General components can be used in various stages – Decode, Encode, Validate etc. Component Category attribute is used to limit use of general pipeline to restricted stages. In my example, I am restricting my pipeline to be used in Decode stage only. This concept is called “Stage Affinity”. Please read following MSDN link to learn more about this –


7. Implement members of IBaseComponent interface.

        public string Description




                    return "Pipeline component used to change namespace of message";



        public string Name




                return "SampleGenPipelineComponent";



        public string Version




                return "";




Member properties are overriden to provide description, name and version of pipeline component.

8. Implement members of IComponentUI interface.

    public IntPtr Icon




                return new System.IntPtr();



     public System.Collections.IEnumerator Validate(object projectSystem)


            return null;


I have kept things simple and have not provided any pipeline design time icon and validation logic. In actuall implementation, you can add an icon in piepline resouce file and point that in impelemtation. Similarily, you can also verify design time configuration/properties in Validate method and can return all inconsistancies in collection of errors.

9.  Implement members of IPersistPropertyBag interface.

        private string _NewNameSpace;

        public string NewNameSpace


            get { return _NewNameSpace; }

            set { _NewNameSpace = value; }


        public void GetClassID(out Guid classID)


            classID = new Guid("655B591F-8994-4e52-8ECD-2D7E8E78B25C");



        public void InitNew()




        public void Load(IPropertyBag propertyBag, int errorLog)


            object val = null;



                propertyBag.Read("NewNameSpace", out val, 0);


            catch (Exception ex)


                throw new ApplicationException("Error reading propertybag: " + ex.Message);


            if (val != null)

                _NewNameSpace = (string)val;


                _NewNameSpace = "http://AnonymusURL";


        public void Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties)


            object val = (object)_NewNameSpace;

            propertyBag.Write("NewNameSpace", ref val);


First of all, we created “NewNameSpace” property which is used to configure new namespace name at design time.

“Load” method loads value from property bag to pipeline property. “Save” method saves value to property bag from pipeline property. “GetClassID” returns component's unique identifying value in terms of GUID. “InitNew” is used to initialize object to be persisted in component properties. I have not implemented it because I don’t require.

10. Implement members of IComponent interface.

        public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)


            IBaseMessagePart bodyPart = pInMsg.BodyPart;

            StringBuilder outputMessageText=null;

            string systemPropertiesNamespace = @"";

            string messageType = "";

            if (bodyPart != null)


                Stream originalStream = bodyPart.GetOriginalDataStream();

                if (originalStream != null)


                    XmlDocument xdoc = new XmlDocument();


                    XmlElement root = xdoc.DocumentElement;

                    messageType = this.NewNameSpace + "#" + root.Name;

                    outputMessageText = new StringBuilder();

       outputMessageText.Append("<" + root.Name + " xmlns:ns0='" + this.NewNameSpace + "'>");


                    outputMessageText.Append("</" + root.Name + ">");

                    byte[] outBytes = System.Text.Encoding.ASCII.GetBytes(outputMessageText.ToString());

                    MemoryStream memStream = new MemoryStream();

                    memStream.Write(outBytes, 0, outBytes.Length);

                    memStream.Position = 0;

                    bodyPart.Data = memStream;




            pInMsg.Context.Promote("MessageType", systemPropertiesNamespace, messageType);

            return pInMsg;


This is core of implementation. Code flow is –

- First read body part of message … = pInMsg.BodyPart;”

- Then read message content (XML) in stream “… = bodyPart.GetOriginalDataStream();”

- Change namespace of XML content “outputMessageText”

- Create a stream of new XML (with namespace)

- Assign stream back to message body part “bodyPart.Data = memStream;“

- Since namespace has changed, we need to update message type context property otherwise there is a fair chance of message routing failure. “pInMsg.Context.Promote("MessageType",…”. To understand importance of MessageType, please refer “Message Processing” section in link -

- Return message so that it can be consumed by next stages of pipeline and/or message box itself.

11. Coding is complete. Build the project.

Deploy Component and Use

To deploy pipeline component, Copy SampleGenPipelineComponent.dll to “C:\Program Files\Microsoft BizTalk Server 2006\Pipeline Components”.

Pipeline component is now ready to use. In BTS receive pipeline project, add this pipeline component dll in toolbar and then use in decode stage. You will find that you can set value of “NewNameSpace” property at pipeline design time.


This was a sample general pipeline component which can be deployed to decode stage. Similarly, you can create other general pipeline components for requirement specific processing and data massaging. Hope this entry was useful. I am also attaching code zip file ( for any further reference.