Mapping With External Assemblies Part 2

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

imageIf 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.

  1. Add a reference for the RDA.Corporate.EAI.Common.Helper.Methods assembly.
  2. Create and add External Assemblies.xml file (named to your liking) to your map project.
  3. Assign the Custom Extension XML Grid Property.
  4. Add a scriptoid to your map.
  5. Set it's script type to XSLT Call Template.
  6. 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.


image 


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


External Links about BizTalk Mapper Performance

2 comments:

Anonymous said...

This is excellent idea, I never thought about use this! Thanks.

BStott said...

How would you go about debugging the xslt of a map using an external assembly?

Great explanation by the way.