Constructing BizTalk 2004 XML Messages (In an Orchestration) - Choices

Before using a BizTalk XML message inside an Orchestration , it must first be
constructed. In fact ,this is just populating the message with XML. If there is an
attempt to use the message before it is constructed, the following error will appear when 
building the BizTalk project -> use of unconstructed message 'MyMessageNameHere'.
Some messages come pre-constructed, such as messages that originate from a port, but there
will be times when a message needs to be constructed inside of an orchestration.

For example if there is a message inside an Orchestration called msgShippingInfo (that is unconstructed),
and is of type ShippingInfo.xsd and the xsd schema looks like the below:

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="http://ConstructingXMLMessages.ShippingInfo" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" targetNamespace="http://ConsltructingXMLMessages.ShippingInfo" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="ShippingInfo">
    <xs:complexType>
      <xs:attribute name="ShipToAddress" type="xs:string" />
      <xs:attribute name="ShipToCity" type="xs:string" />
      <xs:attribute name="ShipToCountry" type="xs:string" />
    </xs:complexType>
  </xs:element>
</xs:schema>

Then at some point, the message must be populated with some xml as below, before that message can
be used:

<ns0:ShippingInfo ShipToAddress="Some Address" ShipToCity="Some City" ShipToCountry="Some Country"
xmlns:ns0="http://ConstructingXMLMessages.ShippingInfo" />


Below are some options for constructing XML messages, inside of an Orchestration.

1) Create new message(s) from a existing message(s) using a BizTalk Map.
This is one of the more common methods. For example,
I need to map my incoming Purchase Order message to an outgoing
Invoice message. Also keep in mind that you can have multiple input messages and output messages
when mapping. For example within an Orchestration, there is an existing constructed Purchase Order and Shipping messages.
I can then use these two messages to create an Order message.

A simple example is as below: 

 

If you have not done it before :
To create a map with multiple inputs and outputs, create the needed messages
in the Orchestration View. For example , in this case an Order message,
PurchaseOrder Message and the Shipping Message.
Drop a transform shape on your orchestration and then choose the source(input) message(s).
In this case there are two : PurchaseOrder message and Shipping message.
Choose the destination(output) message(s) : Order message.
In the Transform Configuration dialog box, choose -> new map. In this case
a new map is created that looks like the above (minus any of the links and functoids between source and
destination messages). These were put in later.

2) Assign one message to another.
At some point you may need a copy of another message. If msgOrderCopy is of the same type
as msgOrderOriginal, then the below assignment can be done.


Construct msgOrderCopy
{

  msgOrderCopy = msgOrderOriginal;
  //Once the new message is constructed, it can now be modified.
  // For example if the schema for the order has distinguished fields,
  // these can now be set. XPATH can also be used to set the data in (Some xpath examples are further down).
  msgOrderCopy.OrderedBy = "Bob";

}


3) Create a message with the help of a System.XML.XMLDocument variable.

In the below example, the XML to populate the message is hardcoded inside the
expression shape. The XMLDocument variable is initially assigned to the hardcoded XML. The BizTalk message is
then assigned to the XMLDocument variable. The BizTalk message is now good to go.
This is a handy technique especially when the schemas/xml instance messages are small. If the schema
has distinguished fields, then these can then be used to set the attributes in the message with real data, otherwise XPATH
can be used to populate the ID and Name attributes of the below simple XML message. It is also
possible to alter the hardcoded XML with the real data, and then do the message assignments.

construct msgShipping
{
  // Use the Variable varXMLDom to load in some XML
 varXMLDom.LoadXml(@"<ns0:ShippingInfo ShipToAddress=""Some Address"" ShipToCity=""Some City"" ShipToCountry=""Some Country"" xmlns:ns0=""http://ConstructingXMLMessages.ShippingInfo"" />");
  // Assign the BizTalk message to the XMLDom variable. Note this can be accomplished becuase a BizTalk message derives from an XMLDocument.
  msgShipping = varXMLDom;
  // If there are Distinguished Fields available, then
  msgShipping.ShipToAddress = "1 Main Street";
  msgShipping.ShipToCity = "Toronto";
  msgShipping.ShipToCountry = "Canada";
  // If there are no distinguished fields, then XPATH can be used to set the attributes in the message.
  xpath(msgShipping , "//@ShipToAddress") = "1 Main Street";
  xpath(msgShipping, "//@ShipToCity") = "Toronto";
  xpath(msgShipping, "//@ShipToCountry") = "Canada";
 


4) Creating a more complex message using : System.XML.Document, System.XML.XMLNode,System.XML. XMLAttribute, Interim BizTalk Message
The below example, uses the same method as in 3) , but the message is more complicated.
A Looping shape is used to add the order items to an order message. The part of the orchestration that does this
is as below:

 


In the the First Expression Shape, Construct the initial Order Message (With just the Order Header), with the help of a XMLDocument variable
construct msgOrderFromAppending
{
   // Initially create the Order Header part of the Order Message
   varOrderXMLDom.LoadXml(@"<ns0:Order OrderedBy=""SomeBody"" TotalOrderAmount=""0"" xmlns:ns0=""http://ConstructingXMLMessages.Orders""></ns0:Order>");
   msgOrderFromAppending = varOrderXMLDom;

}


In the next expression shape add the order items. Note that in the Orchestration this expression
shape is in a loop, so there are multiple order items being added.


// Construct the Temp Order Message to Append the Node.
construct msgOrderFromAppendingTemp
{
   // First set the XMLDOM variable to the msgOrderFromAppending in the first shape.
   varOrderXMLDom = msgOrderFromAppending;
   // use CloneNode to make a fresh copy of msgOrderFromAppending
   varOrderXMLDom = (System.Xml.XmlDocument) varOrderXMLDom.CloneNode(true);
   // Create a new Order Item Node
   varXMLNodeOrderItemNode = varOrderXMLDom.CreateElement("OrderItems");
   // Create Amount Attribute
   varXMLAttribute = varOrderXMLDom.CreateAttribute("Amount");
   varXMLAttribute.InnerText = "0";
   varXMLNodeOrderItemNode.Attributes.Append(varXMLAttribute);
   // Create Description Attribute
   varXMLAttribute = varOrderXMLDom.CreateAttribute("Description");
   varXMLAttribute.InnerText = "A Description";
   varXMLNodeOrderItemNode.Attributes.Append(varXMLAttribute);    
   // Create Qty Attribute
   varXMLAttribute = varOrderXMLDom.CreateAttribute("Qty");
   varXMLAttribute.InnerText = "0";
   varXMLNodeOrderItemNode.Attributes.Append(varXMLAttribute);    
   // Now append the actual Order Item Node to the XML Instance
   varOrderXMLDom.FirstChild.AppendChild(varXMLNodeOrderItemNode);
   // Now actually construct the Temp message.
   msgOrderFromAppendingTemp = varOrderXMLDom;
   System.Diagnostics.Debug.WriteLine("The output is " + varOrderXMLDom.OuterXml);
}

// Now Set the Real Order Message From the Temp Message.
// This is so we can keep adding messages to the real message, without losing them.

construct msgOrderFromAppending
{
   msgOrderFromAppending = msgOrderFromAppendingTemp;
   // Set the Data in the newly added Order Item Node.
  
   // Now use XPAth to set the Data in the attributes,
   // NOTE: I could of also done this by setting the real data
   // on the XMLAttribute object -> varXMLAttribute.InnerText = "Description for Order Item : " +  System.Convert.ToString(varOrderItemCount) ;

   strvarOrderItemCount = System.Convert.ToString(varOrderItemCount); 
   xpath(msgOrderFromAppending,"//OrderItems[" + strvarOrderItemCount + "]//@Amount") = System  m.Convert.ToString(varOrderItemCount) ;
   xpath(msgOrderFromAppending,"//OrderItems[" + strvarOrderItemCount + "]//@Qty") = System.Convert.ToString(varOrderItemCount) ;
   xpath(msgOrderFromAppending,"//OrderItems[" + strvarOrderItemCount + "]//@Description") = "Description for Order Item : " +  System.Convert.ToString(varOrderItemCount) ; 
}


5) Use a .Net helper class to create the message.

As in the above example , instead of using XMLDOM type code in the orchestration, a helper
.NET class could of been called in the orchestration to create the message.
An example helper class would look like the below, just returning an XMLDocument that could be assigned to
the message inside the orchestration.

public static XmlDocument GetXmlDocumentOrderTemplate()
{
// Code to create the message.

}

Now inside the orchestration, the code to call the .Net helper class to construct the message.

Construct myOrderMessage
{

  myOrderMessage = HelperClass.GetXmlDocumentOrderTemplate 


}

Also look here


Download the above examples , Here

Comments

  • matt December 1, 2004 3:11 PM

    Hi,
    your article was very helpfull regarding message initialization within an orchestration and it solved my problem to initialize my message (by using method 3 of your article) within an orchestration (under BPEL Complince). But the problem is that when i export my orchestration to BPEL i get the error:

    "An internal error occurred in the export component.
    Additional Information: Pointer startIndex and length do not refer to a valid string.
    Parameter name: ptr
    "
    The actuall purpose of orchestration was to export it to BPEL so that i can import it in other "Integration Tools e.g. WebSphere SAP NetWeaver" for my use.
    Would you help me in this regard, what should i do. And much as i have tryed till now i guess that even when i create a message variable of type "System.Xml.XmlDocument" i got the error in exporting orchestration to BPEL.
    plz response me at
    ahtisham_a@yahoo.com
    Bye

  • matt February 3, 2005 4:01 PM

    Really helpful. This is a topic i've been struggling with for ages.

  • TrackBack March 1, 2005 9:22 PM

  • TrackBack April 12, 2005 11:04 AM

  • TrackBack June 16, 2005 3:18 PM

  • TrackBack June 16, 2005 3:18 PM

  • matt August 16, 2005 8:36 AM

    Still, I have no clue on how to construct a message when calling a WebService (one parameter). Exactly what do I need to type in the Message Assign shape? There is no simple explicit 'schema' because it is hidden in the web reference.

    Message_CRM_Request.CustomerID = Message_Poll.parameters.usrTask.CustomerID;
    is correct syntax, but not enough.
    How do I construct Message_CRM_Request?
    I refuse to believe that I have write a whole program for that. If this is too complex, then why do I need BizTalk in the first place?

  • matt August 17, 2005 10:43 PM

    wow it works absolutely fantastic man, I wasted my 2 working days and atlast found this message and it worked like charm Yaaaaaaaa hooooooooooooooooo

  • matt September 23, 2005 6:29 AM

    How do you create one with no parameters? I keep getting an error saying that method name cannot be null. Using method number 3 above.

  • matt October 12, 2005 10:34 AM

    Thanks for a VERY useful article. It helped me a lot. But I have a question - is it possible to delete an attribute in example3 ?

  • matt April 6, 2006 11:47 AM

    Another simple technique is to create a map with the target schema set to the desired schema and the source schema set to any dummy schema. Set at least one dummy value for an element in the target schema. This will generate a message that can be used in an orchestration with the Transform shape.

  • matt April 30, 2006 8:38 AM

    Thanks for a VERY useful article. It helped me a lot.

  • matt May 9, 2006 8:24 PM

    Helped a lot to learn construction of biztalk xml messages

  • matt May 22, 2006 12:27 PM

    Hi,
    I have a schema called Error.xsd with the below structure
    <Error>
    <ErrorDetails>
    <ErrorId/>
    </ErrorDesc/>
    </ErrorDetails>
    <Any>
    </Error>

    In this schema, The <ErrorId>,<ErrorDesc> fields are distinguished.
    I am trying to construct Error Message using this schema inside a construct block with Assignment shape.
    I can set the values for <ErrorId> and <ErrorDesc> directly because they are distinguished.
    My question is i want to assign an another schema message to the <Any> element.
    How to do that inside the construct shape?
    Any Idea Plz??

  • matt May 27, 2006 10:20 AM

    One og the best postings I have seen so far regarding creating messages. Well done and
    thanx for yuor effort. This is helping me a lot.

  • matt July 6, 2006 6:13 AM

    thanks for such a nice article

  • matt September 26, 2006 11:31 AM

    although this is helpful, isnt it just so unhelpful. Hope in future versions you can just do something like

    myMessage = new MyMessageType();

  • Joey Liang April 7, 2007 8:49 AM

  • Greg Smith April 17, 2007 9:21 AM

    Instead of filling your "appending" message with dummy data:

    xpath(msgOrderFromAppending,"//OrderItems[" + strvarOrderItemCount + "]//@Amount") = System.Convert.ToString(varOrderItemCount)

    How would you read the data from a message that you have already received? I am creating multiple messages from a single received message and I want to copy the data from the original message into the new message.

  • matt April 18, 2007 8:02 AM

    Greg, Could you still set the message with dummy data, then use distingusihed fields to set the real data , for example

    newmsg.id = incomingmsg.id

    The other thing you could do within a construct shape is to:

    1) in a message assignement shape, first create the "dummy" message

    2) Then within the same construct shape use a transform shape to invoke a map to map the received message to the "dummy" message.

  • 剑飘红 September 25, 2007 10:51 PM

    一.

  • Dom L December 2, 2007 8:43 AM

    Great article! Exactly what I needed thanks :)

  • A world apart from the everday ... January 14, 2008 9:20 AM

    If you&#39;ve done any work with BizTalk orchestrations you&#39;ve had to construct a message inside

Leave a Comment

(required) 
(optional)
(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS