Monday, April 14, 2014

Mapping ComplexType mixed=True Node

I was pretty proud of my previous solution to a node that may or may not have embedded html. Until I tried to use BizTalk mapper to map said node. Simply linking the node to the target schema node resulted in just the text before the first embedded element being mapped. Aha, I thought, Mass Copy functoid to the rescue . . . but that resulted in just the embedded elements being copied and NONE of the text. I could not find a solution using functoids, so I turned to the reliable Scripting functoid. The following code in an Inline XSLT Call Template functoid worked:

<xsl:template name="CopyMergedTest">
    <xsl:param name="param1" />
    <xsl:element name="<ElementToCopyTo>">
         <xsl:apply-templates/>
    </xsl:element>
</xsl:template>
<xsl:template match="text()">
    <xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
</xsl:template>

Having the final <xsl:template match="@* | node()"> was necessary to copy the embedded tags.

Monday, March 31, 2014

Element with embedded html schema

An incoming document will have a text element, but embedded in that text may or may not be html. The html may or may not have multiple nodes. Since the schema will treat html tags as elements, it is necessary for us to handle this case as if we were receiving xml elements.

To create the xsd schema, it was necessary to use the xs:any element.

So the schema looks like this:

<xs:element minOccurs="0" maxOccurs="1" name="Element">
<xs:complexType mixed="true">
  <xs:sequence>
 <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
  </xs:sequence>
</xs:complexType>
</xs:element>

The mixed attribute on xs:complexType tells us that the element can contain text as well as elements. Setting the minOccurs and maxOccurs on the xs:any element tells us that there may not be any embedded elements (in this case html) and there may be an unbounded upper limit. The processContents="skip" will not validate against a schema, allowing us to have any elements.

http://msdn.microsoft.com/en-us/library/aa547371.aspx

Wednesday, January 8, 2014

Cross Domain MSDTC

I spent a lot of time troubleshooting an error from a BizTalk send port:

 

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.

 

I thought I would summarize my findings.

 

What is MSDTC? Microsoft Distributed Transaction Coordinator. In a nutshell, MSDTC coordinates transactions between the BizTalk Server and SQL Server. For instance, if you have a polling statement in SQL that updates the database, you would not want it to commit if the message fails to get added to the BizTalk MessageBox database. Using MSDTC, the update call will rollback if the messagebox call fails. Without MSDTC, there is a risk of losing messages in this scenario.

 

MSDTC uses NetBIOS name resolution. This was one of the first hurdles I had to overcome as the names were not resolving to the IP address of the servers. To troubleshoot this, an entry was made in the hosts file to resolve the sql server NetBIOS name. No matter what you read, this is not the preferred method of dealing with name resolution. If the IP of the server changes, every host file would have to be modified causing an administration nightmare Because MSDTC uses NetBIOS resolution, not a fully qualified domain name, a way needed to be found to resolve the 'short' name with DNS. There is a setting in Advanced TCP/IP Settings in which you can append a suffix to the short name for resolution. Adding [domain] to this suffix list resolved the name resolution (http://technet.microsoft.com/en-us/library/cc959339.aspx). When this was resolved, we ran into firewall issues.

 

MSDTC uses port 135 to initiate the connection. After that, Remote Procedure Call dynamically allocates a port between 1024 and 65535. Obviously, from a security standpoint, opening that range of ports between servers is not suggested. There is a way to limit the port range using registry settings. At some point, this was done on the [biztalk server] box but was not on the BizTalk server. Changing the registry settings requires a reboot of the BizTalk server. After that was done on dev and the firewall was open to the new range of ports, everything worked correctly. We currently are allocating 200 ports for MSDTC connections between biztalk and [sql server] in development (http://support.microsoft.com/kb/250367).

 

The ability to turn off MSDTC is available in the binding settings of the send port. If the UseAmbientTransactions is set to ‘false,’ your send port will make its sql call without using transaction coordination. This is not a solution, be careful turning this off and know that distributed transaction are not required. This would be safe if your sql call included no updates, just gets.

 

There are also some setting in the Component Services->Computers->My Computer->Distributed Transaction Coordinator->Local DTC that need to be configured. In Properties->Security Network DTC Access needs to be checked as well as allowing all of the inbound and outbound connections. Also, since this is cross domain, No Authentication Required should be checked. Those settings need to match on both servers.