TimRayburn.CustomFunctoids - Logical NOT

The first in a series of posts on my functoids library.  More information can be found here.  While I realize that Logical NOT has been added to the base set of functoids in BizTalk 2006, this class will still be useful for those who want to take the code and compile it under Visual Studio 2003 and use it with BizTalk 2004.  Nothing will be used in this or future functoids which does not compile in both versions. Alright, time for the first functoid.  This first time I will provide a step by step detail of how to create the project and the related references, etc.  In future, this will be skipped for brevity.  Most of this same information can be found by going to C:\Program Files\Microsoft BizTalk Server 2006\SDK\Samples\XmlTools\CustomFunctoid and examining the sample project there which shows how to create custom functoids. To that end, we will need to setup a project for all of these functoids.  Opening Visual Studio 2005, we create a C# project (Sorry Cory) and then create a strong name adjust the AssemblyInfo.cs to use our strong name, because like all BizTalk assemblies this will have to be in the GAC.  Then we need to add a reference to Microsoft.BizTalk.BaseFunctoids.dll, this assembly holds the base libraries off of which we can build functoids and can be found at c:\Program Files\Microsoft BizTalk Server 2006\Developer Tools on most boxes.  When you've reached this point your Solution Explorer should look like the one to the right. Now that the project is created, we need to setup the class.  We'll rename Class1.cs as LogicalNotFunctoid.cs.  Likewise we will rename the class within the file as LogicalNotFunctoid.  All functoids derive from Microsoft.BizTalk.BaseFunctoids.BaseFunctoid and ours will be no exception.  We'll add a default constructor which overloads the same in our base class and your code should now look like this:     1 using System;    2 using System.Collections.Generic;    3 using System.Text;    4 using Microsoft.BizTalk.BaseFunctoids;    5     6 namespace TimRayburn.CustomFunctoids    7 {    8     public class LogicalNotFunctoid : BaseFunctoid    9     {   10         public LogicalNotFunctoid() : base()   11         {   12    13         }   14     }   15 }Next we need to add the necessary code to assign the functoid an ID, and to set the resource file where information such as the name and other information will come from.  Most of this is simple copy-paste from the example in the SDK folder.  We will have also added a CustomFunctoidsResources.resx to the solution to hold all these resources.  I will not detail the creation of the resource file here, if you'd like to learn about this download the source it is fairly self-evident.  Once you've gotten the basic constructor down it should look something like this:   10         public LogicalNotFunctoid() : base()   11         {   12             // Assign a "unique" id to this functoid.   13             this.ID = 24601;   14    15             // Setup the resource assembly to use.   16             SetupResourceAssembly(   17               "TimRayburn.CustomFunctoids.CustomFunctoidsResources",    18               Assembly.GetExecutingAssembly());   19    20             SetName("IDS_LOGGICALNOTFUNCTOID_NAME");   21             SetTooltip("IDS_LOGGICALNOTFUNCTOID_TOOLTIP");   22             SetDescription("IDS_LOGGICALNOTFUNCTOID_DESCRIPTION");   23             SetBitmap("IDB_LOGGICALNOTFUNCTOID_BITMAP");   24    25             this.SetMinParams(1);   26             this.SetMaxParams(1);   27         }Now we need to tell the class how we expect this functoid to be called.  It will need to be part of the Logical group, it should take a minimum of 1 parameter and a maximum of 1 parameter and it should take connections from anything that is not a Record (as Records contain no values).  Add those lines of code and now we look like:   10         public LogicalNotFunctoid() : base()   11         {   12             // Assign a "unique" id to this functoid.   13             this.ID = 24601;   14    15             // Setup the resource assembly to use.   16             SetupResourceAssembly(   17               "TimRayburn.CustomFunctoids.CustomFunctoidsResources",    18               Assembly.GetExecutingAssembly());   19    20             SetName("IDS_LOGGICALNOTFUNCTOID_NAME");   21             SetTooltip("IDS_LOGGICALNOTFUNCTOID_TOOLTIP");   22             SetDescription("IDS_LOGGICALNOTFUNCTOID_DESCRIPTION");   23             SetBitmap("IDB_LOGGICALNOTFUNCTOID_BITMAP");   24    25             this.SetMinParams(1);   26             this.SetMaxParams(1);   27    28             //set the function name that needs to be    29             //called when this Functoid is invoked. This means that   30             //this Functoid assembly need to be present in GAC    31             //for its availability during Test..Map and Runtime.   32             SetExternalFunctionName(this.GetType().Assembly.FullName,    33               this.GetType().FullName, "LogicalNot");   34    35             this.Category = FunctoidCategory.Logical;   36             this.OutputConnectionType = ConnectionType.AllExceptRecord;   37    38             AddInputConnectionType(ConnectionType.AllExceptRecord);   39         } All that remains now is to create the method which will actually perform the Logical Not.  This of course is simple after all of the above as long as you remember that your input value will be a string because all data is a string to XML and as such your boolean will arrive as "true" or "false".  I've written this to use System.Convert.ToBoolen so you can also handle inputs like "y" or "n" and the like.   41         public string LogicalNot(string booleanValue)   42         {   43             bool bVal = System.Convert.ToBoolean(booleanValue);   44             if (bVal)   45               return "false";   46             else   47               return "true";   48         } Now we just need to compile the project, place it in the GAC, put a copy in c:\Program Files\Microsoft BizTalk Server 2006\Developer Tools\Mapper Extensions and then add it to our Toolbox.  The result gives us something like this:  Download TimRayburn.CustomFunctoids Version 1.0

TimRayburn.CustomFunctoids

Another new post series that I've been meaning to start for a while.  This post kicks off the development of a new project called TimRayburn.CustomFunctoids.  The idea behind this project is that, in my not so humble opinion, there are several big gaps in the provided functiods that come with BizTalk.  To that end, I intend to begin a library of functoids that can be used by anyone who would like them, subject to the license for all content on the blog.  Here are the rules I will using to guide the creation of these functoids: As each functoid is completed, a new post to the blog will be created with the details of the implementation and the source code.All functoids will have icons in the theme of the group in which they belong.  For instance String functoids will have a red background, etc.All functoid icons will have a bright blue border for the outer pixel to clearly mark them as being part of an external assembly.All functoid ids will be incremented from a base value of 24,601. (Bonus Question : Where did I get the number 24,601?)The goal of all functoids will be to make maps more clear, not less clear.  Icons will be as descriptive as possible and you will not see functoids like "Lunar Moon Phase Functoid". The first functoid that will be created is a pet peeve of mine ... Logical NOT.

Mapping Fundamentals - XSLT Call Templates

I'm creating a new series of posts related to using the BizTalk Mapper.  I know, it's certainly less sexy than Pipeline Testing Framework (seriously, follow that link) or many other BizTalk subjects, but so much of the magic of BizTalk happens in the mapping. In my experience, when people are introduced to the BizTalk Mapper they get it very quickly.  The user interface is straight forward for most of what you need to do in mapping output.  But certainly not all.  Take for example some data that looks like this : <?xml version="1.0" encoding="utf-8" ?> <MyRoot>   <ref qualifier="D2" value="999999999" />   <ref qualifier="XX" value="999999999" />   <ref qualifier="ZZ" value="XX-YYYYYYYY" />   <nm qualifier="NI" value="999999999" /> </MyRoot>   Your mission, should you choose to accept it is simple.  Output one and only one value to destination schema in a node called Identifier which contains either the value of the 'value' attribute of the 'nm' element if the matching qualifier is 'ZZ' or if that does not exist the 'value' attribute of any 'ref' element containing a 'qualifier' attribute of 'ZZ'.  If neither exists, then output the constant value 'N/A'. The catch?  Both nodes can both exist with the proper qualifier, and 'nm' must take precedence in that case. Now, I've no doubt at all that someone could come up with some combination of functoids which might solve this problem.  But we must remember that in the end a map is just XSLT and this problem is supremely easy in XSLT and extremely difficult with the mapper.  The solution, as you've likely already guessed, is an XSLT Call Template Scripting Functoid. An XSLT Call Template Scripting Functoid lets you inject your own XSLT into the middle of a map.  No need to take the effort of writing the full XSLT yourself if only one or two mappings are giving you trouble.  Obviously to be able to write such a functoid you need to understand XSLT, which if you are mapping is a good skill to have anyway.  In this simple example we don't even have to deal with parameters.  By entering a template as follows, you can solve this problem in a few short lines.   <xsl:template name="MapIdentifier">     <xsl:variable name="nmValue" select="/MyRoot/nm[@qualifier='ZZ']/@value" />     <xsl:variable name="refValue" select="/MyRoot/ref[@qualifier='ZZ']/@value" />     <xsl:element name="Identifier">       <xsl:choose>         <xsl:when test="$nmValue">           <xsl:value-of select="$nmValue"/>         </xsl:when>         <xsl:when test="$refValue">           <xsl:value-of select="$refValue"/>         </xsl:when>         <xsl:otherwise>N/A</xsl:otherwise>       </xsl:choose>     </xsl:element>   </xsl:template>   Some things to remember when working with XSLT Call Templates. Only use these when needed.  I recently heard Roy Osherove give the same advice regarding Regular Expression and he was right.  Both RegEx and XSLT Call Templates are more cryptic and harder for someone coming after you to decipher.  Use them when you must, when they save you time, but don't lean on them for everything. The Template name must be unique within the map.  If you copy-paste the template and don't change the name then only one version will be run.  If you later modify one of them and start going nuts trying to figure out why the second isn't behaving properly, check your names. XSLT Call Templates must create the destination node.  Element or Attribute they don't care, when you write one of these you are taking on the job of outputting that node, namespace and all.  I hope this has been a good quick primer on using XSLT Call Templates.  If you've got a topic you'd like covered, leave a comment! [Post Script : Before anyone comments, the example XML given was deliberately rendered similar to an EDI structure because this is a common problem in EDI mappings.]