The biggest change in BizTalk 2013 and how to undo it

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: 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.


Configuring the AS2 Runtime on BizTalk 2013 – one small caveat

I’ve been doing a lot of BizTalk lately, even by my standards, and a lot of BizTalk installations as well.  I’ve blogged and written (in BizTalk 2010 Patterns) about how important it is to change the default configurations that come out of the BizTalk Configuration Wizard.  The most important item is to create separate BizTalk hosts for processing.  I normally do at least four: send, receive, processing (orchestration), and tracking.  In keeping with this I also create handlers for all the adapters for the send and receive hosts.  I also remove the handlers for the default BizTalkServerApplication host. 


This has led me a small but important detail.  Although BizTalk easily accommodates configuring further features later (like EDI or BAM), I did run into one issue.  The AS2 Runtime configuration creates a SQL receive location (Classic SQL not the WCF kind) and it expects, nay demands, the default host to have a receive handler for the SQL Adapter.  This wasn’t that hard to track down, but could cause headaches for others so I thought I would share.