While the Tracking Profile Editor (TPE) is the standard way to monitor BizTalk processes, it often lacks the flexibility needed for complex custom pipelines. When you need to track data programmatically at the messaging layer, the MessagingEventStream (MES) is your most powerful tool.
MessagingEventStream (MES) is used inside a BizTalk pipeline component to write BAM as part of the messaging transactions, ensuring that your BAM event persistence remains in sync with the BizTalk pipeline transactions.
Messaging Event Streams are asynchronous and store tracking data first in the BizTalk MessageBox database. Periodically, the data is processed and persisted to the BAM Primary Import database by the Tracking Data Decode Service (TDDS). This class is derived from the base class EventStream.
📝 One-Minute Brief
When you need to track data that doesn’t reach an orchestration, or when the Tracking Profile Editor (TPE) is too limited, you must use the BAM API. This post explains how to implement the MessagingEventStream within a custom pipeline component. Key benefits include transactional consistency with the BizTalk Messaging Engine—meaning if the pipeline fails, the BAM data isn’t committed—and the ability to capture metadata or message content at the earliest possible stage of processing.
MES has been available since BizTalk 2004 with SP1.
Normally, we write the code to produce BAM events in the Execute method of the pipeline component. The execute method has two parameters:
- An IPipelineContext: contains the pipeline context
- An IBaseMessage: contains the message being processed.
The pipeline context has a GetEventStream method that returns a MessagingEventStream.
Code sample
To use the BAM API in your pipeline, follow this pattern:
- Initialize the Stream
MessagingEventStream mes = new MessagingEventStream();
- Tracking the Activity
string activityID = "MyOrder_" + Guid.NewGuid().ToString();
// Start the activity
mes.BeginActivity("OrderProcess", activityID);
// Map your data from the message context or body
mes.UpdateActivity("OrderProcess", activityID,
"OrderDate", DateTime.Now,
"Status", "Received");
// It is recommended to flush or the engine handles it at the end of the pipeline
Here is a full example:
public IBaseMessage Execute(IPipelineContext context, IBaseMessage message)
{
//Get the Messaging Event Stream
MessagingEventStream eventStream = context.GetEventStream();
…
//Write to BAM
//Create a new, unique activity identifier to use as the ActivityID in BAM
string activityId = Guid.NewGuid().ToString() + "_" + DateTime.Now;
//Start the activity record identified by activityId
eventStream.BeginActivity("MyTrackingDemo", activityId);
// Updates the activity record.
eventStream.UpdateActivity("MyTrackingDemo", activityId, "MESSAGE_ID", message.MessageID, "TRANSACTION_CREATED", DateTime.UtcNow);
eventStream.EndActivity("MyTrackingDemo", activityId);
// Optional Flush
eventStream.Flush();
}
Using MessagingEventStream within custom pipelines provides a level of precision that the TPE cannot match. It ensures your business’s visibility is as robust and reliable as your message processing.
Found what I was looking for.
Found what I was looking for. There is only one problem with this code.A could not find reference for MessageEventStream. Instead i used var type. Worked fine for me,