Casting between messages and classes demystified(?)
However, as stubborn (and purist?) as I may be I have to admit that some cases just call for the odd manipulation (or creation) of messages as classes in .net helper functions.
And so - it is very fortunate that BizTalk is intelligent enough to allow us to cast one to the other without any fuss.
To those of you who do not know yet it is quite possible to have the following -
A serializable class in any .net language.
A schema that correclty represents the xml representation of that class.
A class (idealy a different one) with a function (usualy static, but doesn't have to be) that accepts a paramter of the class above.
An orchestration that has a message of the schema above.
An expression shape that calls the method in that second class passing the message.
BizTalk will take care of the serialization of the message and will pass an instance of the class to the helper method.
Similarly it is possible to return a class from a function and use that function in an assign shape to create a new message (and, of course, the two approached can be combined as well)
Anyway, we've known that for a while now, and it has worked wonders for us; this technique makes both the functions and the orchestrations that need to use them so much simpler; but recently I nearly went mad when I tried to do just that and kept getting casting errors at build time for - as I thought at the time - no reason at all.
For some reason BizTalk was unwilling to accept that my schema and my class are one.
only after quite a few nerve racking attempts did I find out what I did wrong -
All of our classes have serialization attributes to control the xml generated; mostly we're making sure we use attributes whenever possilbe (as opposed to the default element serialization) and that the attribute/element names are short-ish.
In the particular class I used we had an XmlRootAttribute that set a (different, shorter) name to the root element representing the class; as soon as I removed the name from the attribute (it is optional) VS was happy to compile my orchestration.
It appears that BizTalk needs the root element of the class to have the name of the class; no shortcuts there.
By the way - a few months ago I've published this article suggesting that passing XlangParts as paremeters to helper functions may cause a memory leak.
As this would have prevented us from using this wonderfull casting technique we've asked Microsoft to kindly confirm if indeed my understanding at the time was correct and that one should not pass an XlangPart as a parameter to a function.
As I understand it now, and although it is not very clear from the KB article I've referred to in my post, passing XlangParts is ok as long as the lifetime of the message/part is not shorter than the the lifetime of the parameter - in other words - as long as you don't keep the message or message part in memory in your helper class you should be safe.