BizTalk Mapper Patterns: Calling an external assembly from Custom XSLT in BizTalk Server 2010

Posted: July 29, 2012 in BizTalk
Tags: , , ,

This topic is not new in my blog, I’ve already talked about this in the past: Calling an external assembly from Custom XSLT – Custom Extension XML (Grid Property) however, I decided to revisit this functionality within BizTalk Server 2010 and you will know why soon.

So is usual in complex maps to have scripting functoid with custom inline XSLT, and sometimes is useful to call custom .Net components directly from XSLT.

Create .Net Component

To illustrate this functionality, I decided to create a Class Library project: MapperExtensionsFunctions with a simple class where it is implemented a method to format the numbers in three decimal places:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace MapperExtensionsFunctions
{
    public class MappingFunctions
    {
        public MappingFunctions()
		{
		}

        public string ToDecimalPoint(string Input)
        {
            CultureInfo ciEN = new CultureInfo("en-US", false);

            double ConvertionDouble = double.Parse(Input, ciEN);
            string Output = string.Format("{0:0.000}", ConvertionDouble);
            return Output;
        }
    }
}
How can we extend BizTalk map to support this functionality?

You can add a custom extension xml file to your solution in order to declare the namespace and use a method from a .Net assembly from XSLT.

The extension file should look something like this:

<ExtensionObjects>
  <ExtensionObject Namespace="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0" AssemblyName="MapperExtensionsFunctions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cdbffba4cc751306" ClassName="MapperExtensionsFunctions.MappingFunctions" />
</ExtensionObjects>

Note: “http://schemas.microsoft.com/BizTalk/2003/ScriptNS0” is the “default namespace”, however you can change it (see more here)

In the properties of your BizTalk Mapper, use the Custom Extension XML property to open the Select Custom Extension XML File dialog box, in which you can select the file that contains the custom extension XML for the map (file above).

Custom-Extension-XML

Finally in your Inline XSLT functoid you can use the methods from the assembly by:

<xsl:variable name="result" xmlns:ScriptNS0="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0" select="ScriptNS0:ToDecimalPoint(MarketPrice/text())" />

Or in this case, inside Inline XSLT Call Template:

<xsl:template name="PriceTemplate">
  <xsl:param name="market" />
  <xsl:param name="owner" />
  <xsl:element name="Price">
    <xsl:variable name="pmarket" xmlns:ScriptNS0="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0" select="ScriptNS0:ToDecimalPoint($market)" />
    <xsl:variable name="powner" xmlns:ScriptNS0="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0" select="ScriptNS0:ToDecimalPoint($owner)" />
    <PriceMarket>
      <xsl:value-of select="$pmarket" />
    </PriceMarket>
    <PriceOwner>
      <xsl:value-of select="$powner" />
    </PriceOwner>
  </xsl:element>
</xsl:template>
Houston we have a problem!

After Build, deploy and configure my project with success I decided to test my solution, but I keep getting the following error:

The Messaging Engine failed while executing the inbound map for the message coming from source URL:”C:\TEMP\PORTS\IN_CAR\*.xml” with the Message Type “http://BizTalk.CallingExternalAssemblyFromInlineXSLT.CarInfo#CarProperty&#8221;. Details:”Cannot find the script or external object that implements prefix ‘ScriptNS0′.”

At first glance, this error suggests that the assembly in question is not published in the GAC… However even after re-publish, the assembly in the GAC the problem remained!

Don’t panic, believe it or not, you did everything right… BizTalk Server 2010/Visual Studio 2010 have a bug (or issue): Visual Studio does not persist the path of Custom Extension XML property in the .BTM file.

So if someone wishes to use an external assembly in via a Inline XSLT/XSLT Template scripting functoid they cannot specify the external assembly through an extension xml file.

I tried to install the latest cumulative update package for BizTalk (CU5) and Visual Studio service pack but the issue still remain active (you can see more detail and vote to fix it here)

Workaround (unfortunately it’smanual)

You need to manually edit .BTM file to add this node between the elements </ScriptTypePrecedence> and <TreeValues>:

<CustomXSLT XsltPath="" ExtObjXmlPath=".\ExternalAssembly.xml" />

Note: Is not mandatory the CustomXSLT node stand between the elements </ScriptTypePrecedence> and <TreeValues> however this is normal behavior of the compiler

However this is a workaround that can cause many problems, especially maintaining this issue… but stay tuned, because in my next post I will explain how we can solve this problem in a better way.

Calling an external assembly from Custom XSLT in BizTalk Server 2010 Maps (65.9 KB)
Microsoft Code Gallery

About these ads
Comments
  1. [...] BizTalk Mapper Patterns: Calling an external assembly from Custom XSLT in BizTalk Server 2010 [...]

  2. Jordan says:

    Sandro, I find this method VERY useful. Thanks for posting,I am looking forward to other helpful tips.

  3. Tobi says:

    The issue seems still be present in BTS2013.

  4. RCH says:

    Hi,

    I have a question about the version that should be specified in the custom extension xml file.

    In a context of several assembly versions deployed side by side, I have my extension file referencing the 1.0.0.0 version of a dll, whereas the BizTalk Project containing the map has a dll reference to the 1.0.0.1 version.

    This is causing an “object reference not set to an instance of an object.” error during map execution at runtime.
    I changed the version in the file to 1.0.0.1 and it worked (no new methods or else added in the last version!)

    Does the custom extension points to the project references or directly to the GAC ?

    That’s weird because I don’t have the error according the used environment.

    Thanks!

    • That’s an excellent question… I didn’t try this scenario but for me it makes sense that the custom extension points directly to the file that is deploy in GAC.

      But again I never try this scenario before so I need to test this behavior to have sure.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s