One thing that you learn pretty fast in BizTalk is that messages in an orchestration are immutable/read only.

If you need to modify a message in a BizTalk orchestration, you are pretty well restricted to using a Construct shape with encapsulated Transform and/or Message Assignment shapes to create a modified version or a copy of the original message. Distinguished fields,xpath statements, BizTalk maps, custom .Net components, etc. can be used to modify the message.

Below is one simple technique that can be used to modify a message anywhere in an orchestration.
Helper class(s) are required, but in certain situations (explained below) this technique can be used to easily modify a message anywhere in an orchestration.

Below is an orchestration where this technique is used:


Very simply this orchestration subscribes to a PO xml message and then produces a
final Invoice XML message that is send out from the orchestration.

Below are the artifacts used in the solution:

The artifacts for the BizTalk project, BTS_Immutable_To_Mutable include:

1) ClassOrchestration.odx (Orchestration as above)
2) Invoice.xsd (schema for outgoing Invoice XML message)
3) PO.xsd (schema for incoming PO XML message).
4) InvoiceClassGen.bat and POClassGen.bat

Below is the InvoiceClassGen.bat file:

The above uses the .Net xsd.exe utility to generate an Invoice.cs class from the Invoice.xsd schema.
This Invoice.cs class is used in the Class_Immutable_To_Mutable project as below. 

The artifacts for the Class Library project, Class_Immutable_To_Mutable include:

1) Helper.cs (Helper Class to populate the some of the fields of the Invoice)
2) Invoice.cs (Invoice class for variable in the orchestration)
3) PO.cs (PO class for variable in the orchestration)

This orchestration will:

1) Accept a PO xml message

2) As below, in an expression shape, assign the BTS PO message to a BTS variable message of type PO.cs

// Set the BTS Variable PO to the incoming BTS Message PO
varPO = msgPO;

3) As below, in an expression shape, populate some of the Invoice fields from the PO fields:

// Populate some of the fields in the BTS Invoice Variable,
// from the BTS PO variable fields.
varInvoice.TotalAmt = varPO.Amt;
varInvoice.TotalCount = varPO.Qty;

4) As below, in an expression shape, call a helper class to populate and return the Invoice Items class:

varInvoice.Items = Class_Immutable_To_Mutable.Helper.mapPOItemsToInvoiceItems(varPO);

5) As below, in an expression shape, call a helper class to return and assign the description for the invoice Description field.

// Set the BTS Variable Description field
varInvoice.Description = Class_Immutable_To_Mutable.Helper.GetInvoiceDesc(varInvoice);

6) As below, in an expression shape, call a helper class to return and assign the version for the invoice Version field:

// Set the BTS Message Invoice Version field
varInvoice.Version = Class_Immutable_To_Mutable.Helper.GetInvoiceVersion();

7) Finally at the end, in a Construct/Message Assignment shape, construct the the outgoing BTS Invoice message:

// Create the BTS Invoice message from the Variable Invoice message
msgInvoice = varInvoice;

8) Send out the Final Invoice XML message
So after all of this, could a BizTalk map been used to create the Invoice message from the PO message. The answer is yes or no depending on the mapping logic that is needed.

This leads to when use this method:
Creation of a message requires multiple calls to Helper components/Business Rules to create the message.

Some of the upsides to using this approach are:
1) Using the above technique takes away the restriction of the immutable message and working with a mutable variable in the orchestration.
2) Intellisense is available on the variables inside of the orchestration.
3) The variable can be modified directly in an expression shape inside of the orchestration, without the use of distinguished fields or xpath statements. 

Some of the downsides to using this approach are:
1) The overhead of deserialization and serialization from Message to Variable and visa versa.
2) Creating and maintaining the Helper classes (in this case PO.cs and Invoice.cs)

You can download the above example HERE (Zip File).
Read the Readme before installing and running the example.

For a similar example, goto Here
and download the Using a Custom .NET Type for a Message in Orchestrations example.