While the BizTalk Mapper provides many functoids, complex business logic is often best handled in a custom XSLT file. However, XSLT alone sometimes needs the power of .NET. To bridge this gap, you must use the Custom Extension XML property.
In complex maps, it is usual to have a scripting functoid with custom inline XSLT, and sometimes it is useful to call custom .NET components directly from XSLT.
📝 One-Minute Brief
When standard functoids aren’t enough, developers often turn to custom XSLT. However, calling external .NET assemblies from that XSLT requires a specific configuration: the Custom Extension XML property. This guide explains how to create the extension XML file, map the namespace to your assembly, and configure the BizTalk Mapper’s Grid properties to enable seamless integration between XSLT and external C# code.
So, how can we do this?
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://MapperHelper" AssemblyName="BizTalk.Mapper.Helper, Version=1.0.0.2, Culture=neutral, PublicKeyToken=b39e2eca2a3d19ec" ClassName="BizTalk.Mapper.Helper.MappingHelper "/>
</ExtensionObjects>
or
<ExtensionObjects>
<ExtensionObject
Namespace="http://SandroPereira.ExternalAssembly"
AssemblyName="SandroPereira.MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=yourtokenhere"
ClassName="SandroPereira.MyLibrary.MyFunctions" />
</ExtensionObjects>
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).

Note: There are two cases in which you will need to build your own custom extension XML file and set the Custom Extension XML file to refer to it, as follows:
- If you use the Custom XSLT Path property to specify your own XSLT for the entire map file and you call an external .NET assembly from your XSLT, you are responsible for creating a properly formatted custom extension XML file that provides the appropriate namespace-to-assembly binding.
- If you use the Inline XSLT or the Inline XSLT Call Template script types in a Scripting functoid and you call a method in an external .NET assembly from that XSLT, you are responsible for creating a properly formatted custom extension XML file that provides the appropriate namespace-to-assembly binding. This is required because BizTalk Mapper does not parse into the XSLT you provide, looking for calls to external assemblies. Any binding information you provide by using the Custom Extension XML property will be appended to any binding information that has already been generated when the map was compiled (such as bindings required by other Scripting functoids in the map that use the external assembly option). When you validate the map, the resulting contents of the custom extension XML file contain the union of the binding information you provided and any binding information generated by BizTalk Mapper.
Finally, in your Inline XSLT functoid, you can use the methods from the assembly by:
<xsl:variable name="result" xmlns:myScriptPrefix="http://MapperHelper" select="myScriptPrefix:myConcat($param1, $param2)" />
or
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:userCSharp="http://SandroPereira.ExternalAssembly"
exclude-result-prefixes="userCSharp" version="1.0">
<xsl:template match="/">
<OrderId>
<xsl:value-of select="userCSharp:GetFormattedId(string(InputOrderId))" />
</OrderId>
</xsl:template>
</xsl:stylesheet
By leveraging the Custom Extension XML property, you unlock the full power of .NET within your XSLT transformations. This ensures your BizTalk maps remain robust and capable of handling even the most complex integration requirements.
Hope you find this helpful! If you liked the content or found it useful and would like to support me in writing more, consider buying (or helping to buy) a Star Wars Lego set for my son.
just to let you know i think there is a typo – your two code snippets have different namespaces.
Thanks for the warning Bjorn, I already fixed the typo error.