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>
<?xml version="1.0" encoding="utf-16"?>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
Posted Tuesday, November 09, 2004 8:37 PM
Filed under Newsletter, BizTalk