Message Construction in an Orchestration
Probem
When you are in an orchestration there and you want to create a new instance of a message but not by mapping it from an existing message there are a number of ways this can be achieved. Basically you use a message assignment shape inside of a message construction shape. There is another post which is not bad which explains a number of different ways this can be done. Although they all pretty much do the job I had some concerns about these and tried to come up with an alternative which I preferred. the post to which i am referring is:
http://www.objectsharp.com/Blogs/matt/archive/2004/11/09/1009.aspx?Pending=true
The main reasons I didnt want to use the approaches here are:
1. Use a Map
This one isnt really applicable to this post as i have already said the situation was to create the message without using a map.
2. Assign one message to another
This isnt really applicable to my situation either as this is suitable when both message instances are of the same type. If this is your case then you should use this technique
3.Create a message with the help of a System.XML.XMLDocument variable
My main concern here is that doing this "inline" in the shape has the major problem that if the schema changes then the the code is difficult to maintain and you are not going to catch bugs until you start pushing messages through the orchestration at which point I can imagine this will be quite difficult to troubleshoot.
4. Creating a more complex message using : System.XML.Document, System.XML.XMLNode,System.XML. XMLAttribute, Interim BizTalk Message
See above.
5. Use a .Net helper class to create the message
Of all of the approaches I think this one is my preferred, but I plan to add a little more to the example just to make it a bit more complete in terms of how I have implemented my alternative solution to this problem.
Alternative Solution
The aim of my alternative solution is to provide an easy way to build messages which will also save time in troubleshooting because breaking changes to a schema will be caught as compile errors rather than waiting until testing my orchestration and finding that i forgot to update the string which is used to create my XmlDocument.
The following example describes how it works.
Example
The following picture shows the solution structire for this example. We have two projects, one a BizTalk project with two schemas and an Orchestration. The second project has a class called SimpleResponse which is generated by xsd.exe to represent the SimpleResponse schema. The other class is the one we will use in our Orchestration and it will be explained later.
The below picture shows a simple orchestration which will receive a message based on a simple request schema (SimpleRequest.xsd) and send a response based on another schema (SimpleResponse.xsd). In the picture you can also see the MessageConstruction shape and MessageAssignment shape which are used to construct the response message.
In the below picture you can see we have the two messages in the orchestration view and also in the variables we have a variable called simpleResponseAdapter. This represents a class in the utilities project.
The picture below shows the code of the SimpleResponseAdapter.
The aim here it to use the Adapter design pattern (see here for more info: http://www.dofactory.com/Patterns/PatternAdapter.aspx).
This adapter inherits from the SimpleResponse class. The simple response class is regenerated in the build process by using xsd.exe and pointing to the schema. By using the SimpleResponseAdapter you can set all of the properties as required but you can also retrieve an XmlDocument representing the object.
The below picture shows the expression shape in the orchestration. As you can see by using the SimpleMessageAdapter you can code against it like any normal .net type, and when you want to actually create the BizTalk message you just assign it to the return value of the adapters .ToXmlDocument() method.
This shows how to use the adapter to help you in the construction of BizTalk messages. Some other benefits are:
- Because the type is serializable you can create it in one place and use it elsewhere in your orchestration. This is useful in scenarios where you want to have a message worked with in different parts of a scope (ie: before, in the scope and in an exception handler)
There are some things to be aware of also:
- There will be a slight hit because of the serialization of the type then conversion to an Xml document, although i dont see this as being a major issue especially with smaller messages. It is a trade off to get the benefits of this technique
- Using it across the whole orchestration can result in the state being persisted to the database.
There are some troubleshooting things i came across when developing this technique:
- If you forget to add the serializable attribute to the adapter you can not use it across the whole orchestration. You can still use it within a single expression so long as the state doesnt need to be persisted
- If you forget to set the XmlRoot attribute on the adapter class then you can get some errors about being unable to find the schema if you miss the namespace (when the message is pushed through the Xmlassembler for example) and also it might not serialize as expected if you dont specify the root node name in the attribute.
Conclusion
I hope this post demonstrates a useful technique which can be used as an alternative to the ones put forward in the original article I mentioned. The key point is that all approaches are valid and you need to choose the best one for your situation.