January 27, 2021
Hot Topics:

BizTalk Pipeline Dreams Become Reality

  • By Jeffrey Juday
  • Send Email »
  • More Articles »

As you can see, WritePipelineContext makes prodigious use of the XmlReader and XmlWriter functions. In the XmlWriter class, WriteStartElement creates a new element in an XML document. Another call to WriteStartElement creates a child Element and so on in a hiearchal fashion, until a call to WriteEndElement closes the element.

TestPipelineBindingElement inherits from PipelineBindingElement and overrides the OnBuildChannel function, which in turn creates the TestPipelineChannel. The function implementation is in Listing 3.

Listing 3: The OnBuildChannel function

protected override IPipelineChannel  OnBuildChannel()
   return new TestPipelineChannel();

PipelineBindingElements are contained inside of a PipelineBinding. In the sample code, PipelineBindings are by the StandardPipelineConfiguration class. Implementing a StandardPipelineConfiguration class is the subject of the next section in this article.

Configuration File

There is not much to the anatomy of the StandardPipelineConfiguration class in the sample code. PopulateBinding accepts a PipelineBinding, dynamically loads the assembly containing the TestPipelineChannel classes, and instantiates the TestPipelineBindingElement class. The PopulateBinding function body appears in Listing 4.

Listing 4: The PopulateBinding function.

public void PopulateBinding(PipelineBinding binding)
   //Assembly has no public constructor
   Assembly.LoadFrom(@"C:\Program Files\Microsoft BizTalk Server
                     2006\Pipeline Components\
   PipelineBindingElement element = null;

   element = (PipelineBindingElement)assm.CreateInstance



A complete solution would use some of the techniques above and also read from a configuration file or some other source. Reading a custom configuration file is well documented in the .NET documentation. Unclear in the .NET documentation is how you approach finding the configuration file from within the Pipeline.

Listing 5 shows an approach combining classes from the System.Configuration namespace and the AppDomain class.

Listing 5: Combining classes.

Configuration config = null;
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
string configFile = "file.config";

fileMap.ExeConfigFilename = AppDomain.CurrentDomain.BaseDirectory +
   "\\Pipeline Components\\" + configFile;


if (!config.HasFile)

ExeConfigurationFileMap allows an application more granular control over the loaded configuration file. Pipeline Components are assemblies loaded by the BizTalk Service application. The BizTalk Services executes from the BizTalk installation folder. So, the BaseDirectory property on the CurrentDomain will return the BizTalk installation folder.

Typically, Pipeline Components are stored in the "Pipeline Components" folder inside the BizTalk installation directory. You may ease installation and configuration pains by putting the accompanying configuration file in the same folder containing the assemblies.

One quirk of the OpenMappedExeConfiguration function is that, although the function may succeed, you still should verify that the configuration file is not missing.

Once you're able to find and read a configuration file, the possibilities are almost endless. Here are some other suggested configuration improvements.

  • Some of your classes may expose specific properties. You can format the configuration file to store the properties. If you employ multiple Pipeline Components Channels, each Channel may contain a different section in the Configuration file.
  • By using serialization, you can instantiate a class from XML stored in the configuration file.
  • You're not limited to typical configuration files. If you have more sophisticated needs, you can read a custom file format or even read configuration information from a SQL server database.


You now have seen how to extend the PipelineChannel classes and how to access configuration information. Now, you will learn how to incorporate Business Activity Monitoring (BAM) into the mix along with some other improvements you can make to the sample.

Describing BAM and discussing BAM APIs is beyond the scope of this article. If you are unfamiliar with BAM, look at my BAM article, "Put Some "BAM" in Your Next BizTalk 2004 Project."

PipelineChannels are a perfect place to use BAM APIs. You can separate the BAM API code from other PipelineChannels code putting BAM code in another assembly or implement BAM code in a separate class. Thus, BAM options can be configured in a configuration file instead of baking the information into a Pipeline Component assembly.

You can leverage failed message routing (See "Exceptional Error Handling with BizTalk 2006 and InfoPath") with the pipeline component and invoke BAM dependant upon the BizTalk Context. Studying failed message statistics often exposes potential system improvements.

Separate PipelineChannels can be configured to handle separate BAM data warehouses. So, for example, by reading the BizTalk Context you can call APIs with different parameters.

Future versions of the BAM API will participate in a TransactionScope. You can configure your PipelineChannels to create a TransactionScope object lower in the stack and incorporate the same TransactionScope, using BAM, higher in the Pipeline Channel stack.

Suggested Changes

Pipeline.exe is a great tool for quickly developing the major parts of a Custom Pipeline Component. Without Pipeline.exe, running your code in the debugger requires repeatedly attaching to the BizTalk Service process. Pipeline.exe will save you a lot of time. You can learn more about Pipeline.exe in my earlier article "Build BizTalk 2004 Custom Pipeline Components to Process Non-XML Data."

It's important to point out that I used more than the required number of the Pipeline.exe command line arguments. In the sample, I return the resulting message in Unicode format. You may want to change the formatting option. The BizTalk Pipeline.exe documentation describes all of the command line arguments.

Second, PipelineMessage probably should not contain the BizTalkContext. The context already resides in the PipelineBindingElement, so classes needing the BizTalkContext can get the context there. The ApplyPromotions function should also be removed from the PipelineMessage class; PipelineExecutionContext is probably a better place.


In "BizTalk Pipeline Dreams, Part I," you learned how to build a WCF inspired Pipeline Channel Stack to ease developing one-off BizTalk Pipeline Component solutions. In this article, you expanded that information to create a Pipeline Channel to add to the Channel Stack. I also suggested changes you can apply to your own solution. In particular, I propose using Business Activity Monitoring (BAM) in the Pipeline.

Page 2 of 2

This article was originally published on August 16, 2007

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date