Tuesday, November 19, 2013

Base64 encode/decode part of messages in map

This post is to show how to base64 encode or decode a part of a message (or the entire input message for that matter) and output the resulting string in an element in the output message.

The technique used allows for execution of inline C# (or VB) code from another script functoid using inline XSLT / XSLT Template.

The input and output schemas looks like this:




In the example, our entire input message should be base64 encoded and the resulting string output to the EncodedData element in the output message. This element is of the type xs:string.

First, we create a script functoid to hold our inline C# code for base64 encoding of the input node. When building such a method, one might first try to use string as the datatype for the input which will result in just the inner xml being transferred to the method. This is since the data from our XSLT call will be of the type MS.Internal.Xml.Cache.XPathDocumentNavigator. We therefore declare the input variable as XPathNavigator instead to get access to the full XML node. The base64 encoding is done using the System.Text.Encoding class together with the System.Convert class.

public string Base64EncodeData(XPathNavigator param1)
{
    byte[] bytesToEncode =

        System.Text.Encoding.UTF8.GetBytes(param1.OuterXml);
    string encodedText = Convert.ToBase64String(bytesToEncode);

    return encodedText;
}


This functoid will not be connected to any node, but just left to "hang" in the map since we call it manually from another script functoid. Another solution to have it a bit cleaner would be to place this code in an external assembly and call that, but sometimes it is nice to have everything in the map.

Next we create a script functoid and connect it to the destination element. We set the following Inline XSLT code:

<xsl:variable name="data">
  <xsl:copy-of select="/" />
</xsl:variable>

<xsl:element name="EncodedData">
  <xsl:value-of select="userCSharp:Base64EncodeData($data)" />
</xsl:element>

We first declare a variable that holds a copy of our source node which we simply specify using xpath.
Then we call the previously configured method doing the encoding, and send the resulting data to our created destination element.

The map will now look like this:



The result from sending in a test XML is an XML with the entire original contents base64 encoded in an element.



Wednesday, November 6, 2013

Pay attention when running Biztalk Server and SQL Server on servers in different timezones

This post discusses what most likely is a seldom encountered setup, but nevertheless a possible one. Consider a global company that is using BizTalk. For various reasons, the SQL cluster will have Windows configured with another timezone than the rest of the servers.


This is our mock setup. BizTalk is located in the U.S. and at UTC-5 while the SQL server is in Sweden at UTC+1.

During normal operations, this will work just fine. Each server will locally run in it's own timezone and all is good. The issues appear when working with service windows.

Let's create a receive port with a corresponding receive location pulling in files from a folder.

Now we want to use a service window on this receive location to only allow files to be processed during two hours every afternoon. This is in a real world scenario most likely going to be set up with a time reference to the BizTalk Server, i.e. the service window time will match the timezone on the BizTalk Server. In our example, it's 16:00 to 18:00 that is allowed, UTC+1.



If we look in the corresponding table in the SQL Server for this receive location, we can see that the time is set accordingly.



However, when the BizTalk Server rolls up to this time, the receive location will still not pull the file in! Why is that?

Well, it seems that when BizTalk is checking if the receive location should be active or not, it compares the stored service window time with the local time on the SQL Server. BizTalk is after all heavily based on SQL Server. This have the effect that the time that we set on the BizTalk machine in UTC+1 and which is stored as such but without the timezone information will be used as is and hence be offset by six hours in this example.

If we change the service window time in the BizTalk Administration Console to be offset with the corresponding six hours (i.e. 16:00 will be 10:00 instead), the receive location will trigger at the intended time.

So far so good. If you know about this issue, it is easy to work around it. However, if you add in the normal complexity regarding daylight saving time that will change the offset yet a little twice a year, you are most likely heading towards a small headache!