Custom disassembling and orchestration: Could not find a matching subscription for the message?

Ah, believe it or not, my mailbox fills up with requests for help! Oh, well. Today, some folks which I assume would like to remain anonymous are puzzled by a custom disassembling pipeline problem. Let's see if we can help them.

Here is the e-mail I received, formatted to fit this page. I took the liberty to highlight in red the relevant parts of this message, this was not in the original message:

[...] I went through your article on custom pipeline dissembler. I have a similar requirement of parsing the Flat file input to XML document, so I tried the same code with some changes. But was not able to achieve the goal. I get an error

  1. Could not find a matching subscription for the message
  2. The Messaging engine failed to process a message submitted by adapter: FILE Source URL:C:\PO\*.txt. Details: Could not find a matching subscription for the message. This error occurs if the subscribed orchestration schedule or send port has not been started, or if some of the message properties necessary for subscription evaluation have not been promoted. Please refer to Health and Activity Tracking tool for more detailed information on this failure

[...]
Amit [Name protected].

Since I cannot share the code that was attached to that e-mail, I'll describe the issue. There is a receive pipeline with a disassembler similar to mine . A very simple proof of concept orchestration (one receive shape that has the "Activate" property set and one send shape) is supposed to pick up the message and then send it to an other port. When run, the error outlined above appears and the message is set in the suspended, not resumable state.

What went wrong?

BizTalk needs to know which message an orchestration expects. This is called a subscription. In this specific example, BizTalk does that by looking at the type of message on the receive shape. It has the "Activate" property on so a new instance of an orchestration should start when a message with this type starts. When you built the orchestration, you specified the schema for the receive shape (it was the "Message Type" property). In this case, BizTalk defines the activation message type as the concatenation of the namespace of the schema and the root element. So if the namespace is http://schemas.microsoft.com/BizTalk/PO and the root node is "PurchaseOrder", the message type that will trigger your orchestration is going to be http://schemas.microsoft.com/BizTalk/PO\#PurchaseOrder.

To figure out the type of a message, BizTalk will look at the "MessageType" property that is stored within the context associated with any message in BizTalk. This property is promoted.

So the question now is to figure out how this property gets populated. In practice (and in most of the samples), you receive an XML document and your pipeline was XMLReceive. In that case, the XMLReceive pipeline will recognize the message and will populate this property for you. It will "just work". In fact, if you intend to receive XML files, you cannot use the pass-through receive pipeline for this exact reason, as explained here

However, when you write a custom dissassembler, the messaging engine has no way to know which message you produced. As a result, it cannot by default populate this "MessageType" property. Your message makes it all the way through the pipeline, reaches the message box and because there is no "MessageType" property, the messaging engine does not know that the message is intended to start a new instance of an orchestration. If your system does not have any other subscription to pick this message based on other properties (file name, pipeline ID ...) the engine finds itself in a situation with a message that cannot be routed to any destination. It then suspends it and emits the error above.

There are many ways to fix this. One obvious one is to populate the property in our custom disassembler. This can easily be done by changing the code as follow:

for (int iProp = 0; iProp < originalMsgContext.CountProperties; iProp++)
{
string strName;
string strNSpace;

object val = originalMsgContext.ReadAt(iProp, out strName, out strNSpace);
// If the property has been promoted, respect the settings
if (originalMsgContext.IsPromoted(strName, strNSpace)) newMsg.Context.Promote(strName, strNSpace, val);
else
newMsg.Context.Write(strName, strNSpace, val);
}

// Insert the following code to promote the MessageType property
string systemPropertiesNamespace = "http://schemas.microsoft.com/BizTalk/2003/system-properties";
string messageType = "http://testDisassmbler.testSchema#Tables";
newMsg.Context.Promote("MessageType", systemPropertiesNamespace, messageType);

Of course, you should replace my sample namespace name in messageType with your actual schema name as explained above. Hopefully, that helped our friend Amit.