Wednesday, August 10, 2011

Message - "The MSDTC transaction manager was unable to push the transaction..."

A client recently saw a strange error after installing a new BizTalk 2010 application. The app produced the following error when using the WCF SQL adapter to connect to a remote SQL database:

The adapter failed to transmit message going to send port "RequestMessageData" with URL "mssql://". It will be retransmitted after the retry interval specified for this Send Port. Details:"System.Transactions.TransactionManagerCommunicationException: Communication with the underlying transaction manager has failed. ---> System.Runtime.InteropServices.COMException: The MSDTC transaction manager was unable to push the transaction to the destination transaction manager due to communication problems. Possible causes are: a firewall is present and it doesn't have an exception for the MSDTC process, the two machines cannot find each other by their NetBIOS names, or the support for network transactions is not enabled for one of the two transaction managers. (Exception from HRESULT: 0x8004D02A)

At first I thought the error might have to do with the fact that the SQL address is virtual. But after some flopping about like a fish on deck, we found a guy at the client site who knew MSDTC really well. He suggested that we choose the "Enable XA Transactions" option in the DTC properties dialog box. I didn't know it at the time, but the production DB was in SQL 2000, running on an older version of Windows. The QA DB had been SQL 2005.

That fix didn't work by itself (there was another issue), and then I remembered that I once ran into something like this when installing BizTalk 2004 for another client. In that case, I had to select "No Authentication Required" in the MSDTC properties on all boxes. But since I knew that no request was going to be coming from SQL 2000, I selected "Incoming Caller Authentication Required". Problem solved!

Tuesday, August 02, 2011

BizTalk Map - Copy Node containing HTML

I recently had to map data from an InfoPath 2007 form to a canonical schema. The input from InfoPath usually contained HTML, although on occasion it contained encoded HTML (depending on where the original data was pulled from). The output needed to be in a CDATA section so that it could be treated as plain old text.

After consulting several people at work and looking at lots of blog posts, I was able to pull off a solution. I'm sure there are ways to improve the quality of the code, but it does work. One thing I don't like about this solution is that it adds a namespace attribute to the top level HTML nodes. Fortunately every browser I tested with ignores the namespace.

Here's the source schema:

And here's the contents of the Inline XSLT functoid that I used:

<xsl:element name="ns0:FreeformData1" >
<xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
<xsl:when test="count(/*[local-name()='myFields']/*[local-name()='FreeData1']/child::*/child::node()) &gt; 0">
<xsl:for-each select = "/*[local-name()='myFields']/*[local-name()='FreeData1']/child::node()">
<xsl:copy-of select="self::*" />
<xsl:value-of select="string(/*[local-name()='myFields']/*[local-name()='FreeData1'])" disable-output-escaping="yes"/>
<xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>

If the input XML looks like this:

<ns0:myFields xmlns:ns0="">
<ns0:field1>Test data</ns0:field1>
<ns0:FreeData1><html><FONT color="#ff0000">Hello</FONT> world this <STRONG>is a test</STRONG></html></ns0:FreeData1>

Then the output XML looks like this:

<ns0:yourFields xmlns:ns0="http://sample2forblog">
<ns0:field>Test data</ns0:field>
<ns0:FreeformData1><![CDATA[<html xmlns:ns0=""><FONT color="#ff0000">Hello</FONT> world this <STRONG>is a test</STRONG></html>]]></ns0:FreeformData1>

I'm not showing the case where the HTML is encoded, but I did test that as well. Encoded HTML is handled by the "otherwise" case in the XSLT above.