Archive BizTalk Messages from an Orchestration Without using a Send Port

In a previous installment of the series of articles describing a lightweight, yet useful, archiving and re-submission solution, I talked about how to store and retrieve BizTalk messages to database.

Initially, the solution was designed to be called from a custom pipeline component. Indeed, you might have noticed that the code for storing and retrieving messages exclusively dealt with the IBaseMessage interface, that is the representation of a BizTalk message as it transits through a pipeline.

Motivation

In our project, we have been building a somewhat ESB-like BizTalk solution, wherein the messages all have the same type, that corresponds to a single consistent XML envelope as their body part. This envelope contains a set of properties that allow messages to be routed to their target via direct-binding and message subscriptions.

When something goes wrong in one of our orchestrations, we wanted to archive the corresponding message and, all its associated parts, in the database for later submission and completion of the business process.

In that scenario, we did not want our message to go through the BizTalk Message Box as part of the archiving process. Indeed we would have encountered "infinite loops" when multiple instances of the same subscribing orchestration would have been trying to perform their work on the message.

Therefore, we tried to alter our message archiving helper library so that we could send a message to the database directly from within an orchestration.

The Problem

Well… I said that I "tried". Although I still have not entirely given up, it turns out that its seems quite difficult in fact to do what I want.

In BizTalk orchestrations, messages are represented by the XLANGMessage class. One of the most obvious problem I encountered is that this class does not expose a way to retrieve the entire context of the message. This class also suffers from other minor problems. For instance, as far as I know, it does not seem possible to identify which of the message parts is the Body part. Similarly, it does not seem possible to retrieve the entire properties of a message part with the XLANGMessagePart API.

The Solution

Backtracking on this endeavour, the only solution that I could find was to actually call a pipeline from within the orchestration. The pipeline would contain a custom pipeline component that in turn would call the archiving IBaseMessage-based helper library.

However, since I wanted the archiving process to be as simple as possible, I wanted to create an "archiving pattern" so that it could be repeated from one orchestration to the next. However, the number of shapes required in an orchestration to call a pipeline quickly renders this pattern unwieldy.

Fortunately, all of this can be replaced with a single C# helper method, that can then be called inside an Expression shape within our orchestrations.

The code looks like the following:

public static class ArchiveDbManager
{
    public static void ArchiveMessage(XLANGMessage message)
    {
        // XLANGMessage instances are reference-counted in
        // the BizTalk runtime so make sure we dispose of them

        try
        {
            SendPipelineInputMessages messages = new SendPipelineInputMessages();
            messages.Add(message);

            XLANGMessage output = message;
            XLANGPipelineManager.ExecuteSendPipeline(
                  typeof(MessageDbArchiveTransmit)
                , message
                , output);
        }
        finally
        {
            message.Dispose();
        }
    }
}

It can then be called inside an Expression shape like so:

ArchiveDbManager.ArchiveMessage(msgSample);

That’s it. A one-liner ultra-simple archiving helper for use in all our message archiving needs.

This entry was posted in BizTalk. Bookmark the permalink.