BizTalk Server 2006 Custom Functoid Documentation Mistake

When you develop a custom functoid, there are 5 important tasks to do:

  1. Create a resource file with the various resources such as functoid’s name, description, tooltip and icon.
  2. Create the class that will implement the functoid. This class must derive from the Microsoft.BizTalk.BaseFunctoids.BaseFunctoid class.The constructor must override the bas class constructor and call a certain number of methods and properties so that the custom functoid can run properly at run-time as well as integrate well into the Visual Studio’s mapper.
  3. Create a member method in the functoid class that will actually implement the functionality of the custom functoid (its business logic).
  4. Compile and sign the functoid project into an assembly with a strong name key file (so that the assembly containing the custom functoid can be deployed in the GAC).
  5. Copy the assembly to C:\Program Files\Microsoft BizTalk Server 2006\Developer Tools\Mapper Extensions and add the functoid in Visual Studio’s ToolBox. You must also install the assembly into the GAC so that the functoid is available to BizTalk at runtime.

Today I found out that the BizTalk Server 2006 documentation has a mistake in the custom functoid development section: Using BaseFunctoid, which relates to the point number 2 in my previous list of tasks.
That section says that the constructor of the functoid must make a call to the SetupResourceAssembly method to point to the resource assembly. It details:

Include a resource file with your project. If building with Visual Studio, the resource assembly must be ProjectName.ResourceName.

In my experience this is not true, when I build my custom functoid assembly in Visual Studio, I have to call the SetupResourceAssembly method with FunctoidNameSpace.ResourceName as parameter instead of ProjectName.ResourceName. If I follow the documentation’s advice, the resource information such as functoid’s name and icon do not appear in Visual Studio’s toolbox, proving that the resources could not be found by the IDE.

The only case that it would work as mentioned in the documentation would be if the project name and the namespace of the functoid were identical, which happens by default in Visual Studio. Indeed, when you create a new project with Visual Studio 2005, a default namespace will be created for the project, its value being the project name. You can see the default namespace value by right-clicking on your project files and click “properties”.

Using the Enterprise Library in Biztalk Functoid.

Enterprise Library.

The Enterprise Library is a set of .Net application blocks providing many useful features that can be re-used across projects. I find it now a more mature library which developers can rely on. At the time of writing, the Enterprise Library 3.1 is available at the Microsoft Patterns & Practices site.

Custom Database BizTalk Functoid implementing Caching.

I created a BizTalk functoid which is responsible to lookup values into a database. This particular lookup not being a simple query, a custom functoid was required. With the database lookups becoming a bottleneck when mapping larger messages, I had to implement a caching strategy within the functoid.
I chose to go with the Enterprise Library to implement the caching functionality as it provides nice features such as scavenging and expirations (similar to the ASP.NET cache engine). Some people might think of using the ASP.NET Cache instead but I did not and I would not advise it. Although some people say it is possible to use it outside ASP.NET application, it is not recommended by Microsoft so I did not even try to go down that road. See the System.Web.Caching.Cache reference.

Enterprise Library application block configuration.

The Enterprise Library instantiates objects through the use of a static factory. The application blocks’ factories create objects and configure them by using information from a configuration file, by default the web.config or app.config XML config file – depending if it’s a running from an executable or an ASP.NET page.

The BizTalk runtime is also a .Net application, so it has an XML config file called BTSNTSvc.exe.config which is located in the root folder where BizTalk is installed.
As the functoid using the Enterprise Library Caching application block will run from the BizTalk runtime, the application block configuration will need to reside in BTSNTSvc.exe.config. It is important to remember that all BizTalk hosts running on a BizTalk server will use the same BTSNTSvc.exe.config file. This is somewhat some kind of limitation.
Note that it is possible to use other configuration source than the default .Net .config file, see the Enterprise Library documentation for more details.

Adding a component in the Visual Studio Toolbox.

Adding a custom functoid in the Visual Studio Toolbox is pretty straightforward. See http://msdn2.microsoft.com/en-us/library/aa559309.aspx
Note that if you deploy the BizTalk solution on the same machine you develop, you will have to add the functoid in the GAC so that the map using it will be able to find it at runtime.

One important thing to know is that when adding a component in the Visual Studio Toolbox, the component constructor is called. This is because the Visual Studio design time service needs to retrieve some of the component properties to be able to display and modify them in the properties window.
Most of you know that when working with .Net Windows Forms, all components or controls have a constructor which calls the InitializeComponent() method where all the properties and members of the component are initialized.
This initialization is of course needed for runtime but also for design time, so that’s why a component’s constructor is called during design time as well.

Example of design time properties for a Windows Application Form control (Button).

The Button control properties are displayed in the “properties” windows correctly because an instance of the component has been initialized by the Visual Studio design time service, so its properties have been initialized and can be read and displayed by the IDE.

In the case of a BizTalk functoid, the same mechanism exists, the properties which are needed for design time are initialized in the constructor.
For example, the functoid’s name, tooltip, description and also the functoid bitmap used to display the functoid in the toolbox and in the mapper editor are set in the constructor using calls to inherited methods:
SetName(“ResourceKeyForFunctoidName”);
SetTooltip(“ResourceKeyForFunctoidToolTip”);
SetDescription(“ResourceKeyForFunctoidDescription”);
SetBitmap(“ResourceKeyForFunctoidBitmap”);

Example of design time properties for a BizTalk functoid (Cumulative Sum)

Example of design time properties for a custom BizTalk functoid

As you can see, it is obvious that the Visual Studio Design time environment needs to make an instance of the component so that it can evaluates all its properties to display in the Visual Studio IDE.

Adding the custom functoid in the Toolbox is not working / Testing a map using the custom functoid throws an exception.

During design time and when testing a map, the Visual Studio runtime is used to instantiate and call methods on the functoid. This means that until the configuration block is configured for Visual Studio, the application block’s static factory won’t find its configuration and an error will occur when the call to the application block’s static factory runs.
This error will happen either when:
– adding the functoid in the toolbox, if the call to the application block factory is in the functoid constructor
– testing a map using the functoid, if the call to the application block factory is in the functoid method.
The solution to this problem is to add the application block configuration in the Visual Studio IDE config file, devenv.exe.config, typically located at C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\

Conclusion:

To summarize, when using the Enterprise Library in a BizTalk project – such as a functoid or any other piece of custom code, the application block configuration information must be stored in the BTSNTSvc.exe.config (for the BizTalk runtime) and devenv.exe.config (for the design time experience under Visual Studio runtime).