As I said earlier, been doing a lot of BizTalk lately and I’m definitely loving the BizTalk 2013 changes. The XSLCompiledTransform is one of the things I’ve been really happy to see. I’m planning some real Side by Side benchmark numbers for a blog soon, but this is a feature that I think came out of research Paolo Salvatori wrote about in How To Boost Message Transformations Using the XslCompiledTransform class. Paolo you are my hero.
I was recently working on a very large very complex BizTalk implementation that is being upgraded and stumbled upon some very strange behaviors I could not fully understand. The first issue was that maps that I have good reason to believe are exactly as they are working in production now started to fail during testing. Eventually I tracked down that the maps used inline C# in scripting functoids and did not mark them as public. At first I thought the code must have been changed in these maps, but it hadn’t (thanks ILSpy). So I tried the maps back on an older BizTalk machine and sure enough, they worked. I know the XslCompiledTransform replaced the XslTransform class back when .NET 2.0 came out (and was happy as I did a lot of XSLT and XML in .NET before my BizTalk days). I also know BizTalk 2013 uses this much faster transform class. I decided to check out Migrating From the XslTransform Class on MSDN. Sure enough there was my answer under Extension Objects and Script Functions:
XslCompiledTransform introduces two new restrictions on the use of script functions:
- Only public methods may be called from XPath expressions.
- Overloads are distinguishable from each other based on the number of arguments. If more than one overload has the same number of arguments, an exception will be raised.
So this was a bummer, but thanks to some handy RegEx skills I found all the places this was an issue in every map in the very large solution quite quickly (one of my computer science professors is smiling right now).
So life was good, or so I thought. Deeper into testing some results were not as they were expected. I looked at these issues and again ended up looking at maps with inline C# in scripting functoids. Testing these maps on my workstation I could see they were not working as I had expected. It seemed like implicit Boolean conversion issues were happening. I changed a few maps and went on with my work, but eventually the scope of the issue dawned on me. This wasn’t some maps, it was all the maps that used inline C# (which is something I don’t like anyway) with Boolean parameters. Now I had a real problem. I reached out to the super-secret group of BizTalk experts I’m a part of, but I must not have used the proper secret handshake as no one replied.
I got my testing to the point that I could walk through the maps, which was complicated by the fact that they also used external classes (thank you Maxime Labelle for Debugging XSLT Stylesheet with Custom Extension Objects from Within Visual Studio). I ended up dropping the method calls and extension objects and being able to reproduce this just inside of Visual Studio with XSLT debugging. The strange part was that the value in question would be a Boolean in the XSLT debugger. The BizTalk Mapper turns all such parameters into strings (for good reason) and even debugging the string($valx) in Visual Studio returned the correct value, but as soon as the .NET method was invoked the parameter would be passed in as true – no matter what, even if it was false.
Eventually, exasperated I turned to a Premier Field Engineer from Microsoft who I had crossed paths with. I showed him what was happening and he confirmed I hadn’t completely lost my mind – or at least not on this issue. He soon came back to me with this: http://support.microsoft.com/kb/2887564/en-us which despite my best Bing-ing I was unable to find myself (I even tried that other search engine out of desperation, but nothing). Here was the answer! As I read on I grew slightly concerned that this would be a “by design” sort of answer like other software companies give, but this is Microsoft! The company whose biggest weakness is staunchly maintaining backwards compatibility IMO – another blog perhaps. But there was hope, further in the article was my salvation:
It is also possible to configured the BizTalk 2013 Transform Engine to use the older XSLTransform class. This approach is not recommended since the environment will lose the many performance and memory usage improvements provided by the XSLCompiledTransform class. This change can be made by adding DWORD UseXslTransform with value 1 at the following locations:
- For 64 bit BizTalk host instances: HKLM\SOFTWARE\Microsoft\BizTalk Server\3.0\Configuration
- For 32 bit BizTalk host instances and Visual Studio’s Test Map functionality: HKLM\SOFTWARE\Wow6432Node\Microsoft\BizTalk Server\3.0\Configuration
Not only was there a way around it, it was already built into the product! No patch, or hotfix, or anything!
I know I’m losing performance with this, but I’m also not changing dozens or hundreds of maps either. BizTalk ran fine before and will run fine still for these needs.
Thank you to the BizTalk development team for doing this right and to that PFE who saved my bacon.