For a proof of concept I needed to start working on today at work involving BizTalk Server 2004, I needed a quick way to create a number of send ports (between 10 and 20), configured in a very specific manner each one (say, with a specific combination of filters and stuff like that).

Before spending a lot of time creating them by hand (a pain!), I decided to check out what BizTalk could offer to do this programatically. Turned out to be fairly painless using the BizTalk Explorer Object Model (in Microsoft.BizTalk.ExplorerOM.dll).

I decided to write a quick sample to show how it is done, perhaps someone will find it useful out there. The code just creates a SendPort called MySendPort, configured witht e XMLTransmit pipeline, the FILE adapter on a specific filesystem folder, and sets up a filter on the port that ties it to one of two receive ports. Here's the code to do it:

//
// CreatePort.cs
//
// This is a sample application that uses
// the BizTalk Explorer Object Model
// to create a send port configured with a
// few filters.
//
// Author:
// Tomas Restrepo (tomasr@mvps.org)
//
using System;
using System.Collections;
using Microsoft.BizTalk.ExplorerOM;
namespace Winterdom.BizTalk.Management.Samples
{
///
/// Application class.
///

public class CreatePortApp
{
public static void Main(string[] args)
{
//
// Create the CatalogExplorer and connect
// to the management database
// we should definitely pick up the connection
// string from the DB
//
BtsCatalogExplorer om = new BtsCatalogExplorer();
om.ConnectionString = "Server=(local);Database=BizTalkMgmtDb;Integrated Security=true";
CreatePort(om);
// once we are done we should
// persist changes to the DB again.
om.SaveChanges();
}
///
/// Create the send port
///

/// Catalog Explorer object
public static void CreatePort(BtsCatalogExplorer om)
{
//
// Create a new Send port, configured as
// static, One Way port
//
SendPort port = om.AddNewSendPort(false, false);
port.Name = "MySendPort";
//
// Create a new filter with this:
// BTS.ReceivePortName == 'MyReceivePort' OR
// BTS.ReceivePortName == 'MyReceivePort2'
//
string filter =
@"

Operator='0'
Value='MyReceivePort'
/>


Operator='0'
Value='MyReceivePort2'
/>

";
port.Filter = filter;
//
// Configure the primary transport and the
// send pipeline to use
//
TransportInfo transport = port.PrimaryTransport;
transport.Address = @"c:\temp\%MessageID%.xml";
transport.TransportType = FindProtocolType(om, "FILE");
port.SendPipeline = om.Pipelines["Microsoft.BizTalk.DefaultPipelines.XMLTransmit"];
}
///
/// Finds the appropriate ProtocolType instance
/// from the list or registered transports
///

/// Catalog Explorer object
/// Name of the adapter
/// The ProtocolType instance
public static ProtocolType
FindProtocolType(BtsCatalogExplorer om, String adapter)
{
for ( int i =0; i < om.ProtocolTypes.Count; i++ )
{
if ( om.ProtocolTypes[i].Name == adapter )
return om.ProtocolTypes[i];
}
return null;
}
} // CreatePortApp
} // namespace Winterdom.BizTalk.Management.Samples

The overall code is actually fairly simple, though some things are not as intuitive as one might expect. Some things to keep in mind are:

  • Filters are defined using an XML syntax, where each Group in the filter represents an AND group. This means that each group has a set of properties that are AND'edd together, and then groups are OR'ed together.
  • The adapter that a port uses is configured on the transport, as an instance of the ProtocolType class. To find the one you want, I believe one should look at the ProtocolTypes collection on the Catalog Explorer object. This collection, however, is only indexed by position, so you have to iterate through it until you find the one you want by looking at its name.
  • This one caught me by surprise: The Pipelinelines collection of the Catalog Explorer object is indexed by the type name only (namespace + class name), not by fully qualified type name (namespace + class name + assembly name).

Hope someone finds this useful...


Tomas Restrepo

Software developer located in Colombia.