Introduction
Part 1 - Inline scripting and external assemblies
Part 2 - XSLT Call Templates and custom extensions
Part 3 - Cascading Functoids
This is the second of three articles about BizTalk mapping with external assemblies. External assemblies or helper classes are used by BizTalk's mapping engine (XSLT) automatically, and they can also be used explicitly by the developer. Just as in an orchestration, a developer may find a requirement that the built in mapping tools ("functoids") do not address and in this case judicious use of a helper class can be very... helpful.
While these articles are not an introduction to mapping if you have a little experience with the BizTalk mapper and a little experience with XSLT you should be able to follow along.
Part 1, introduces inline C# scripting, its limitations, and also introduces the scenario of using an external assembly (helper class) automatically. Part 2, this article, demonstrates using a map's custom extension property, which allows us to explicitly access external assemblies. Part 3 will build on this discussion and highlight potential caveats about using cascading functoids; when the output of one functoid is the input to another functoid(s).
External Assembly Script Type Review
In part 1 we examined inline scripting with C# and pointed out that only the built-in XSLT engine namespaces can be used. We also showed that when using an External Assembly Script Type an Extension Object XML file is automatically created, which contains the external assembly references that the XSL will use.
The contents of the Extension Object Xml file that is made during the build looks like this:
<ExtensionObjects>
<ExtensionObject
Namespace="http://schemas.microsoft.com/BizTalk/2003/ScriptNS0"
AssemblyName="RDA.BizTalk.Learning.MapUtility,
Version=1.0.0.0,
Culture=neutral,
PublicKeyToken=f7eb52812c0b3fa1"
ClassName="RDA.BizTalk.Learning.MapUtility.Strings" />
</ExtensionObjects>
Custom Extension Xml Property
If we want to explicitly include external assemblies in our map we can assign the "Custom Extension Xml" Grid Property. Click on the background (grid) of your map in design mode to find the properties. The property represents an Xml file that is formatted as shown above, and it will contain only those assemblies that you wish to manually reference. As we will see, other assemblies referenced by External Assembly Script Types will be automatically appended to this file during the build.
I normally name my file "External Assemblies.xml". The following is an example. I usually leave the Namespace as the Namespace of the class. That way if I have one assembly (as I do below) I will have 2 unique namespaces. Remember, your external assemblies are probably already in the GAC.
<ExtensionObjects>
<ExtensionObject
Namespace="http://RDA.Corporate.EAI.Common.Helper.Methods.Timestamps"
AssemblyName="RDA.Corporate.EAI.Common.Helper.Methods,
Version=1.0.0.0,
Culture=neutral,
PublicKeyToken=9f177c4f1a417459"
ClassName="RDA.Corporate.EAI.Common.Helper.Methods.Timestamps"/>
<ExtensionObject
Namespace="http://RDA.Corporate.EAI.Common.Helper.Methods.DBUtility"
AssemblyName="RDA.Corporate.EAI.Common.Helper.Methods,
Version=1.0.0.0,
Culture=neutral,
PublicKeyToken=9f177c4f1a417459"
ClassName="RDA.Corporate.EAI.Common.Helper.Methods.DBUtility"/>
</ExtensionObjects>
Using the Referenced External Assemblies
We already know that unfortunately we cannot use these classes with inline C# scripting. However, we also know that ultimately the mapper is simply creating XSLT and calling the C# methods, and we can do the same.
Let's pretend, for example, that based on a meeting number, room number and timestamp that I need to retrieve a meeting record id. My DBUtility class contains the methods I need to use.
- Add a reference for the RDA.Corporate.EAI.Common.Helper.Methods assembly.
- Create and add External Assemblies.xml file (named to your liking) to your map project.
- Assign the Custom Extension XML Grid Property.
- Add a scriptoid to your map.
- Set it's script type to XSLT Call Template.
- Assign input parameters, and assign the output to the target schema node as required.
Here is my map, I'm going to enrich the original message by filling in the MeetingKey record. I'll be using an XSLT call template. Remember it is the XSLT that is driving the mapping within the scriptoid. See the next paragraph.
Here is my XSLT call template that I've assigned to my scriptoid shown above.
<xsl:template name="MeetingKeyCallTemplate">
<!--Meeting Key Input -->
<xsl:param name="meetingNumber" />
<xsl:param name="roomNumber" />
<xsl:param name="meetingTimestamp" />
<!-- Get the meeting key and assign it to variable -->
<xsl:variable name="meetingKey"
<!-- I'll just use the prefix "script" which is easy to type -->
xmlns:script="http://RDA.Corporate.EAI.Common.Helper.Methods.DBUtility"
<!-- Call my external method GetMeetingKey() -->
select="script:GetMeetingKey($meetingNumber,
$meetingTimestampDateTime,
$roomNumber)"/>
<!-- Emit the MeetingKey and modified attribute values -->
<MeetingKey>
<xsl:attribute name="modified">Yes</xsl:attribute>
<xsl:element name="id">
<xsl:value-of select="$meetingKey"/>
</xsl:element>
</MeetingKey>
<!-- Emit the MeetingNumber, RoomNumber and MeetingLeader fields -->
<MeetingInfo>
<xsl:element name="MeetingNumber">
<xsl:value-of select="$meetingNumber"/>
</xsl:element>
<xsl:element name="RoomNumber">
<xsl:value-of select="$roomNumber"/>
</xsl:element>
<!-- Note: The MeetingLeader value comes directly from the original message -->
<xsl:element name="MeetingLeader">
<xsl:value-of select="MeetingInfo/MeetingLeader/text()"/>
</xsl:element>
</MeetingInfo>
</xsl:template>
TIP: In part 3 we'll see similar code again and we will combine into one example the use of external assemblies, inline C# scripting and value caching in a discussion about cascading functoids.
Custom Extension XML and External Assembly Script Types
The BizTalk mapper will accommodate maps using both custom Extension XML file as described here and also uses External Assembly Script Types. In this case the Extension Object XML file that is used will combine your custom references along with the automatically added External Assembly Script Type references. Validate your map and check it out!
External Links from MSDN
- Custom Extension XML (Grid Property)
- Scripting Using External Assemblies
- Scripting Using Inline C#, JScript .NET, and Visual Basic .NET
- Scripting Using Inline XSLT and XSLT Call Templates
- Extending Mapper (BizTalk Server Sample)
External Links about BizTalk Mapper Performance
2 comments:
This is excellent idea, I never thought about use this! Thanks.
How would you go about debugging the xslt of a map using an external assembly?
Great explanation by the way.
Post a Comment