Hi all

It is pretty common that developers want to assign one message to another inside and
orchestration. And as we all know, this must happen inside a “Construct Message” shape.

Inside the “Construct Message” shape, you can have several shapes, but they must all
be either a “Transform” shape or a “Message Assignment” shape. The “Transform” shape
is used to execute a map, that will generate the message(s) that is/are to be constructed.
The “Message Assignment” shape on the other hand uses the expression editor to let
you specify how to assign a value to the message(s) that is/are to be constructed.

Often, there is a need to basically copy a message and then change just a couple of
values in the copied message. This can’t be done by changing the values of the existing
message, as messages in an orchestration are immutable.

Creating the copy is pretty simple; You just assign one message to another like this:

 1: OutputMessage
= InputMessage;

Now, what many people realize after doing this and something does not work, like routing,
correlation or other is, that this assignment only copies the content of InputMessage
to OutputMessage. The context is not copied at all. So what you can do is to add another
line of code to your “Message Assignment” shape like this:

 1: OutputMessage
= InputMessage;

 2: OutputMessage(*)
= InputMessage(*);

This will copy the context of a message from one message to another but not the entire
context, as it turns out.

I was trying out a demo for property demotion, and for this I let my orchestration
receive an input message, transform it to an output message and send this out.

So what I did was that I created two schemas:

inputschema and outputschema

I let Field1 and Field3 be promoted into the same promoted property from a custom
property schema, and I let Field2 and Field 4 be promoted into another property in
a custom property schema.

and a map that does not map anything – it just created empty fields for Field3 and
Field4.

In my “Construct Message” shape, I then added a “Transform” shape to do the transformation
and a “Message Assignment” shape that would copy the properties. I then wanted to
make sure the output of the send port had the demoted values inside it.

What I expected to happen was this:

  1. The XMLReceive pipeline would receive the input, promote the two properties and publish
    the message to the MessageBox.
  2. The Orchestration would pick it up, perform the transformation, copy the context and
    send the message out.
  3. The XMLTransmit pipeline would demote the two values from context (that I had copied
    from the input message) into Field3 and Field4

This didn’t happen, though. No values were demoted at all. Now, not demoting into
Field4 was expected, since demotion doesn’t work for attributes (or does it? See my
blog post coming up in a very short time 🙂 ), but I really expected something to
turn up in Field3.

It turns out, that this statement from my code:

 1: OutputMessage(*)
= InputMessage(*);

does not copy ALL the context, but only the promoted properties that are marked as
MessageContextPropertyBase. The ones that are marked as MessageDataPropertyBase (which
is the default) do not get copied over. Now, this actually makes sense, all though
it baffled me at first, since properties marked as MessageDataPropertyBase are based
on values inside the message, so they cannot just be copied to another message type,
since BizTalk cannot guarantee that this property exists on this message type and
that the element that points to the promoted property actually exists in the message.
Well, I guess BizTalk COULD guarantee that, but Microsoft have chosen not to implement
that.

Also, distinguished fields, which are also in the context of the message are not copied
over – again, this makes sense, since these are tightly bound to the schema they come
from (This doesn’t stop the mapping engine of copying them over in maps on receive
ports, though, which is really silly – see here).

SO, in order to get ALL the context copied form my input schema to the output schema,
I needed three lines of code:

 1: OutputMessage(*)
= InputMessage(*);

 2: OutputMessage(DemotionTest.Property1)
= InputMessage(DemotionTest.Property1);

 3: OutputMessage(DemotionTest.Property2)
= InputMessage(DemotionTest.Property2);

or I could mark the properties as MessageContextPropertyBase.

Yes, indeed So remember this from now on:

  1. Assigning one message to another does NOT copy over the context
  2. Copying over context using M2(*) = M1(*) does NOT copy over custom properties that
    are marked as the default (MessageDataContextBase)
  3. In order to get the rest of the properties copied over, do it manually or change the
    type of the properties, if applicable.

I hope this helps someone



eliasen