Extending BizTalk 2004: Create an Encryption Functoid

The last few weeks I’ve been pretty busy with BizTalk 2004 (those of you who are in my Messenger buddy list can whiteness that) and I must say it’s for a full 100% a product of the new Microsoft generation. What I mean by that is that everything is so extensible... You need to do something special in a receive pipeline? Just create the component in .NET and drop it in your receive pipeline. You need custom treatment of a message? Just create the component and drop it in an orchestration. And none of these customizations are rocket science, everyone with some decent knowledge of .NET can do it! To prove it, let’s create a custom Functoid that allows you to encrypt/decrypt values in your messages.

First of all: what the heck is a Functoid?

 This is the definition from the glossary: An executable module that performs a specific calculation or data manipulation, and that is used graphically when constructing BizTalk Server maps to provide the basis for richer transformations than what is provided by XSLT on its own. (Btw: a updated set of the BizTalk documentation is coming on the second of April!). So it’s an tiny little component that you can use in the BizTalk Mapper when you transform a message to another message. There are quite a lot of Functoids already available out-of-the box in BizTalk 2004, going from simple string functions to more complex lookup’s in database tables. There are even Functoids in which you can type C# or VB.NET code that will be executed dynamically. Therefore the need for custom Functoids is in fact not very high, only in some cases where you need specific functionality repeatedly or you need the higher performance of compiled code, a custom Functoid can come in handy.

Imagine the following situation: you’re designing the EAI layer of a company that has to deal with credit card information of it’s customers. Probably you’re a little worried because you’ll be sending XML messages containing sensitive data to all sort of legacy systems. Of course you can use secure communication channels like HTTPS, but your manager really wants to have an extra layer of encryption for specific elements of your XML messages. So in the messages you’ll be receiving, the CreditCardNumber field will be encrypted, thus you’ll have to decrypt that field before you send it further. Let’s create some Functoids that can help us with the decryption and encryption!

Important note: the following example is meant to explain how to create a custom Functoid, it is not meant to illustrate a security best-practise!

You can create Functoids in a Class Library project in Visual Studio.NET, so let’s create one, and name it “SecurityFunctoids” for example. We’ll need a reference to the Microsoft.BizTalk.BaseFunctoids.dll assembly that is located in the Developer Tools directory of your BizTalk installtion (probably X:\Program Files\Microsoft BizTalk Server 2004\Developer Tools). This assembly contains the base Functoid class from which we’ll inherit. Since the assembly we’re creating will need to be deployed to the GAC, we’ll need to give it a strong name, so put the location of your public/private key pair in the AssemblyKeyFile attribute in the AssemblyInfo.cs file. Also in the AssemblyInfo.cs file add the Guid attribute, generate a new Guid for your Functoid (for VS.NET interoperability) and give you’re assembly a meaningful title:
[assembly: System.Runtime.InteropServices.Guid("2E345003-E2B0-47c3-89CB-3AC93A824064")]
[assembly: AssemblyTitle("SecurityFunctoids")]

Next we’ll need to add an Assembly Resource File to the project (Resources.resx for example) that will contain for each Functoid following items:

  • Name
  • Description
  • ToolTip
  • Bitmap (will be showed in the ToolBox)

I prefer to use the Resourcer tool to create resource files, it allows you to easily add various kinds of data (like text, bitmaps, …) to your resource file.

Now we’re ready to write some code! Add a new class to your project: DecryptionFunctoid, and use following code:
using System;
using Microsoft.BizTalk.BaseFunctoids;
using System.Reflection;
namespace SecurityFunctoids
{
            public class DecryptionFunctoid: BaseFunctoid
            {
                        public DecryptionFunctoid()
                        {
                                   this.ID = 6002;
                                   SetupResourceAssembly("SecurityFunctoids.Resources", 
                                               Assembly.GetExecutingAssembly());
                                   SetName("ENCRYPTION_NAME");
                                   SetTooltip("ENCRYPTION_TOOLTIP");
                                   SetDescription("ENCRYPTION__DESCRIPTION");
                                   SetBitmap("ENCRYPTION__BITMAP");
                                   this.SetMinParams(2);
                                   this.SetMaxParams(2);
                                   SetExternalFunctionName(GetType().Assembly.FullName, 
                                               "SecurityFunctoids.EncryptionFunctoid", "DecryptString");
                                   this.Category = FunctoidCategory.String;
                                   this.OutputConnectionType = ConnectionType.AllExceptRecord;
                                   // Parameter 1
                                   AddInputConnectionType(ConnectionType.AllExceptRecord);
                                   // Paramter 2
                                   AddInputConnectionType(ConnectionType.AllExceptRecord); 
                        }
                        public string DecryptString(string val1, string val2)
                        {
                                   SymmetricEncryption enc = new SymmetricEncryption();
                                   return enc.Decrypt(val1, val2);
                        }
            }
}

As you can see, the class inherits from the BaseFunctoid. In the constructor there are a number of things set:

  • Unique ID of the Functoid (start from 6000 for your own Functoids).
  • Name, Tooltip, Description and Bitmap resource strings.
  • The maximum and minimum number of parameters your Functoid will accept. In our case both are set to two. The first parameter will be the value to decrypt, the second parameter will be the key to use.
  • The SetExternalFunctionName determines which function of the class will be used when the Functoid is invoked, in our case the DecryptString function.
  • The category is specified by using the Category property.
  • The parameters of the Functoid are configured.

Then the function that will do the work is written next: DecryptString. I’ve used a helper library for encryption and decryption of string values, so I won’t go into detail about encryption/decryption functionality. Finally build your project so we can use it in BizTalk. The deployment of a Functoid consist of three steps:

  • Deploy it to the GAC
  • Copy it to the X:\Program Files\Microsoft BizTalk Server 2004\Developer Tools\Mapper Extensions directory (So Visual Studio.NET can use it)
  • Add it to the ToolBox in Visual Studio.NET (right click on the ToolBox, choose Add/Remove items, click the Functoids tab and browse to the SecurityFunctoids.dll file and make sure it’s checked.

If you’ve deployed your Functoid correctly you should be able to see it in the ToolBox:

To use the new Functoid you can create a similar orchestration as showed below:

The DecryptMessage Transform shape should contain String Decryption Functoid:

For samples of more advanced Functoids check out Scott Woodgate’s blog post.

5 Comments

  • Hi Jan,



    Thanks for the article, just wondering if the code is correct. The line:



    SetExternalFunctionName(GetType ().Assembly.FullName, "SecurityFunctoids.EncryptionFunctoid", "DecryptString");



    refers to the class EncryptionFunctoid,

    but the class name is

    DecryptionFunctoid.



    Also, is there a rererence to the SymmetricEncryption class needed?

    (Would it be possible to post a ZIP of the project?)



    I am having a real hard time with custom functoids, are there any pitfalls to watch out for?



    All the best,



    Alan





  • You're right! My mistake...



    I've used a library containing the encryption stuff. Because it wasn't the goal of my post to explain encryption/decryption i've not posted the code of that. If you're intrested you can send me an email using the Contact link.

  • Hi Jan, Thanks for a nice article. I have created a library of functoids, and setup resource bitmaps for them using 16x16 pixel bmps generated using paint. These were added to the resx file using Lutz's Resourcer.

    Basically everything works fine except, that the bitmaps do not show up in the toolbox. The name is there from teh resx file, but there is a blank space where the bitmap should be in the toolbox.

    BUT, if you drag one of my functoids onto a map designer, then the bitmap is dispayed fine. It is also displayed fine when you use the Add/Remove items on the toolbox, when you click on the functoid in the functoids tab.



    The name info from the resx file changes as I change the strings in the resources, so i know it is using the latest versions of the resx.



    Your example uses the FUNTOID_BITMAP ident for the resx file, I have just used the filename of the file as it was added (i.e. "VFBM01.bmp")

    But I tried using it the way you describe but that didn't seem to fix it.



    I am puzzled, as the bitmaps seem fine for most of the parts of the tool, except the toolbox itself.



    Any help would be most appreciated.



    Thanks, Chris

  • This value of the string in following line should map with the name you gave it in the resource file:

    SetBitmap("ENCRYPTION__BITMAP");



    Could you verify that?

  • Whan I created my library, I used Lutz's Resourcer. Using this tool, the name of the bitmap resource is automatically set to the filename of the bitmap e.g. FBM01.bmp.



    I left it like that, but changed the functoid code

    e.g. SetBitmap("FBM01.bmp");



    I did wonder whether it didn't like the ".", so I also tried calling my bitmap resource FUNCTOID_BITMAP instead of FBM01.bmp and changed the functoid code

    e.g. SetBitmap("FUNCTOID_BITMAP");

    But it didn't change anything.



    The strange thing is that the bitmaps do appear when dragged onto the designer and also in Add/remove items for the toolbox...?

Comments have been disabled for this content.