Posted by: techsavygal | February 28, 2006

Creating Custom Functoids in BizTalk Server 2006…

Hi All,
I am sure many BizTalk Developers would have tried this out earlier and there are good posts by Jan and Scott on how to create Custom Functoids in BizTalk Server 2004.
However to assist new bees, lets quickly go through how to create a custom functoid.
 

What is Custom Functoid?
A custom functoid is a custom method you call to perform an operation. This operation can be same or different from the existing functoids. For example, the developer can create a functoid to add 3 numbers instead of 2 or can create an encryption functoid or aggregate functoid,etc.
How to create Custom Functoid?
A custom functoid can be created in any of the .net compliant language like C# or VB.Net. This functoid has to be derived from the class Microsoft.BizTalk.BaseFunctoid and provide implementation for some virtual methods by overriding them.
While implementing the Custom functoid, the user can choose to either expose their code inline or outline. The inline code of the functoid which does the actual functoid computation work maybe written in any .Net complaint language such as C#, VB.Net, Jscript.Net, XSLT,etc. If the use exposes his/her code as inline scripts, the Mapper compiler will extract the inline code for each of these functoids and embed them inline inside the compiled XSLT code when you compile the project.
If the user does not want to expose any inline code, then the mapper will generate XSLT code for his/her code which will call this into the external functoid assembly where this custom functoid resides. In this case, the user has to ensure that the custom functoid assembly is available in GAC for the XSLT engine to be able to find the assembly while doing the Test Map at development time in Visual Studio during runtime.
The following methods are available in BaseFunctoids class which can be overridden to create custom functoids:
public void SetupResourceAssembly(string resourcesName, Assembly resourceAssembly)
Sets the base name of the resources, and the resource assembly which contains these functoid resources. Mapper will use these parameters to instantiate the System.Resources.ResourceManager to load the appropriate resources for the functoids like functoid Name, ToolTip, Bitmap etc. For example if all the custom functoid resources are embedded in the same custom functoid assembly itself with the base name as “MyCustomFunctoids.MyCustomFunctoidsResources”, the following function call will correctly setup the resource assembly:
            SetupResourceAssembly(“MyCustomFunctoids.MyCustomFunctoidsResources”, Assembly.GetExecutingAssembly());
public void SetTooltip(string resourceID)
Specifies the resourceID that will be used to set the ToolTip of the Functoid. The resourceID should be present in the Resource Assembly that is set in the SetupResourceAssembly(..) function.
 

public void SetDescription(string resourceID)
Specifies the resourceID that will be used to set the Description of the Functoid. The resourceID should be present in the Resource Assembly that is set in the SetupResourceAssembly(..) function.
 

public void SetBitmap(string resourceID)
Specifies the resourceID that will be used to set the Bitmap of the Functoid. A bitmap resource with the corresponding resourceID should be present in the Resource Assembly that is set in the SetupResourceAssembly(..) function.
 

public void SetMinParams(int minparams)
Specifies the minimum number of input parameters this functoid can accept. Should be a positive integer greater than or equal to zero.
 

public void SetMaxParams(int maxparams)
Specifies the maximum number of input parameters this functoid can accept. Should be a positive integer greater than or equal to zero.
 

public void AddInputConnectionType(ConnectionType connectionType)
Specifies the Type of nodes that can be connected as inputs to a functoid The ConnectionType enum is defined in the BaseFunctoids dll. This enumeration has a FlagsAttribute attribute that allows a bitwise combination of its member values.
 

public bool HasVariableInputs {get; set}:
Gets or sets the Boolean flag if the functoid can accept variable number of inputs. If this property is set to true, the functoid has no real limit to the number of inputs it can accept. This property should not be used along with methods SetMinParams and SetMaxParams. When this attribute is set to true, the functoid has to provide functions that can accept variable number of inputs.
 

public int ID {get; set}:
Gets or sets the ID of the functoid. IDs from 100 through 4000 are reserved by Microsoft for Base Functoids that ship with the product. Choose IDs that are out of this range for all your custom functoids. Usually it is good to start with a number 6000 and upwards for all the IDs that will be part of your custom functoids.
 

public FunctoidCategory Category {get; set}
Gets or Sets the functoid category to which this functoid belongs. This determines the Tab on which this functoid will be shown in the VS.Net Functoid toolbox. The FunctoidCategory enum is defined in the BaseFunctoids dll.
 

public ConnectionType OutputConnectionType {get; set}
Gets or Sets the output connection type of this functoid. This determines the type of nodes to which the output of this functoid can be connected to. The ConnectionType enum is defined in the BaseFunctoids dll. This enumeration has a FlagsAttribute attribute that allows a bitwise combination of its member values.
 

public InlineGlobalHelperFunction RequiredGlobalHelperFunctions {get; set}
Gets or Sets the list of all predefined Global functions that are used by the Functoid’s inline script. InlineGlobalHelperFunction is an enum that has a list of commonly used functions in functoid scripts like IsNumeric, IsDate, ValToBool etc. This enumeration has a FlagsAttribute attribute that allows a bitwise combination of its member values. Setting the RequiredGlobalHelperFunctions property with the list of required global functions will make sure that these global functions will be automatically included in the compiled XSLT that is generated by the Mapper Compiler.
 

public void SetExternalFunctionName(string assemblyName, string className, string functionName)
Specifies the external function that needs to be called when this functoid is invoked. The assemblyName parameter represents the fully qualified name of the assembly in which this external function resides. The className parameter represents the name of the class in which this function is declared. The functionName parameter represents the actual name of the external function. When the Mapper Compiler generates the XSLT for the Map, all the calls to this functoid will be replaced with calls made to this external function residing in this external assembly. Thus this functoid need not have any inline script that gets included with the XSLT that is generated by the Mapper Compiler. For example the following code sets up the external function for a string concatenation functoid. This function is defined in the same custom functoid assembly, and in a class called “FunctoidSample.CustomStringConcatFunctoid” and has a name “ConCatStrings”.
SetExternalFunctionName(GetType().Assembly.FullName,
   “FunctoidSample.CustomStringConcatFunctoid”, “ConCatStrings”);
The external assembly that is specified in this function should be present in the GAC so that the Map can be executed correctly while doing Test…Map in the VS.Net environment, or during runtime of BizTalk.
 

public void SetExternalFunctionName2(string functionName)
public void SetExternalFunctionName3(string functionName)
The above two functions are used for setting the external function names in case of Cumulative functoids. They are to be used in conjunction with SetExternalFunctionName in case of Cumulative functoids. In case of cumulative functoids, the Mapper Compiler needs three functions for each functoid. The first function is used for doing any Initialization. The second function is used for performing the actual operation in a loop. The third function is used to get the final result of accumulation. The sample Custom functoid code that ships with the product has a cumulative functoid sample. So for example if the custom functoid represents a Cumulative Add functoid which accumulates values over a loop, then the following code correctly sets up the required external functions for this functoid.
SetExternalFunctionName(GetType().Assembly.FullName,
  “FunctoidSample.CumulativeMultiplyFunctoid”,”InitCumulativeMultiply”);
            SetExternalFunctionName2(“AddToCumulativeMultiply”);
            SetExternalFunctionName3(“GetCumulativeMultiply”);
 

public void SetScriptBuffer(ScriptType scriptType, string scriptBuffer)
Specifies the actual inline script that is offered by this functoid. Mapper Compiler will extract the inline script buffer that is set in this functoid, and include it in the final XSLT that is produced during the Map compilation process. The scriptType parameter is used to specify the language of the inline script (possible values are ScriptType.CSharp, ScriptType.VbNet, ScriptType.JSharp etc). Setting the script buffer will make the functoid standalone because the necessary script buffer is extracted and included in the final XSLT that is produced by the Mapper compiler. Setting an external function name (by using the functions such as SetExternalFunctionName, SetExternalFunctionName2, SetExternalFunctionName3) is not necessary when directly setting the script buffer. Most functoids that ship with the product setup their inline script buffer using this function, so that the compiled XSLT can be standalone without any runtime dependency on the custom functoid assembly. For example the following code sets up the inline C# script for a simple concat functoid.
           
String scriptBuffer = @”public string ConCatStrings(string val1,
string val2)
                                                            {
                                                                        return val2+val1;
                                                            }”;
            SetScriptBuffer(ScriptType.CSharp, scriptBuffer);
 

public void SetScriptBuffer(ScriptType scriptType, string scriptBuffer, int functionNumber)
Use this overloaded version of this method (which takes an additional functionNumber parameter) to specify the script buffers in case of a cumulative functoid which needs three functions. The valid values for the functionNumber parameter are 0, 1 and 2. The scriptBuffer with functionNumber of ‘0’ is used for doing any Initialization. The scriptBuffer with functionNumber of ‘1’ is used for performing the actual operation in a loop. The scriptBuffer with functionNumber of ‘2’ is used to get the final result of accumulation.
 

public void SetScriptGlobalBuffer(ScriptType scriptType, string scriptGlobalBuffer)
Specifies any global script buffer that will be used by this functoid. This is a nice way of declaring and maintaining any global variables that will be used across all the functoids during the map execution. For example in case of a cumulative functoid, we may want to maintain a global variable that keeps track of the accumulation results. Since this variable will be global in scope it will accessible in all the individual functoid scripts. The following code declares a global arrayList variable for keeping track of accumulation results of a cumulative functoid.
String scriptGlobalBuffer = ”public System.Collections.ArrayList myCumulativeArray = new System.Collections.ArrayList();\n”;
            SetScriptGlobalBuffer(ScriptType.CSharp, scriptGlobalBuffer);
 

public virtual string GetInlineScriptBuffer(ScriptType scriptType, int numParams, int functionNumber)
Override this function if the functoid can take variable number of inputs. This function will be used whenever the property HasVariableInputs is set to true. During Map compile time, the Mapper compiler will call this function with appropriate number of parameters. This function should then return the correct script buffer accommodating those many input parameters as specified in the parameter numParams. The sample custom functoid code that ships with the product has a sample functoid that can accept variable number of inputs.

Now, lets see a sample Custom Functoid which is used to concatenate two strings:

1. Create a VS 2005 solution

2. Add Microsoft.BizTalk.BaseFunctoids.dll to references.

3. Create the methods derived from Base Functoids class as below:

  public class ExtractArray : BaseFunctoid
 {
  public ExtractArray() : base()
  {
   this.ID = 3005;

   // resource assembly must be ProjectName.ResourceName if building with VS.Net
   SetupResourceAssembly (“Microsoft.Samples.BizTalk.CustomFunctoid.CustomFunctoidResources”, Assembly.GetExecutingAssembly());

   //Setup the Name, ToolTip, Help Description, and the Bitmap for this functoid
   SetName(“IDS_EXTRACTARRAYFUNCTOID_NAME”);
   SetTooltip(“IDS_EXTRACTARRAYFUNCTOID_TOOLTIP”);
   SetDescription(“IDS_EXTRACTARRAYFUNCTOID_DESCRIPTION”);
   SetBitmap(“IDB_EXTRACTARRAYFUNCTOID_BITMAP”);
   SetExternalFunctionName(GetType().Assembly.FullName, “Microsoft.Samples.BizTalk.CustomFunctoid.ExtractArray”, “GetArrayValueByIndex”);

   AddScriptTypeSupport(ScriptType.CSharp);
   
   this.Category = FunctoidCategory.String;
   this.OutputConnectionType = ConnectionType.AllExceptRecord;
   this.RequiredGlobalHelperFunctions = InlineGlobalHelperFunction.IsNumeric;
   
   //this functoid accepts exactly two parameters.
   this.SetMinParams(2);
   this.SetMaxParams(2);

   AddInputConnectionType(ConnectionType.AllExceptRecord);
  }
 As you can observe, we have overridden the following methods from BaseFunctoids class:

  • ID – generates unique ID to the functoid
  • SetToolTip.SetDescription,SetName, SetBitmap – to create resources for our custom functoid.
  • The maximum and minimum number of parameters your Functoid will accept.In our case both are set to two. The first parameter will be accept the string to be concatenated, the second parameter will be concatenated string.  
  • The SetExternalFunctionName determines which function of the class will be used when the Functoid is invoked, in our case the GetArrayValueByIndex function.  
  • The category is specified by using the Category property.
  • The parameters of the functoid are configured.

I have exposed my code as inline which performs the concatenation operation on the input 2 strings as below:

builder.Append(“public string GetArrayValueByIndex(string ignoreParam, string val)\n”);
    builder.Append(“{\n”);
    builder.Append(”    int index = 0;\n”);
    builder.Append(”    if (IsNumeric(val))\n”);
    builder.Append(” {\n”);
    builder.Append(”  index = Convert.ToInt32(val, System.Globalization.CultureInfo.InvariantCulture); // no need to exception check here because IsNumeric already did that\n”);
    builder.Append(” }\n”);
    builder.Append(” if (index >= 0)\n”);
    builder.Append(” {\n”);
    builder.Append(”  if (index >= _globalArray.Count)\n”);
    builder.Append(”  {\n”);
    builder.Append(”   return \”\”;\n”);
    builder.Append(”  }\n”);
    builder.Append(”  else\n”);
    builder.Append(”  {\n”);
    builder.Append(”   return (string) _globalArray[index];\n”);
    builder.Append(”  }\n”);
    builder.Append(” }\n”);
    builder.Append(” return \”\”;\n”);
    builder.Append(“}\n”);

Finally build the project so that we can use this functoid 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 2006\Developer Tools\Mapper Extensions directory (So Visual Studio 2005 can use it)  
  • Add it to the ToolBox in Visual Studio 2005 (right click on the ToolBox, choose Add/Remove items, click the Functoids tab and browse to the Customfunctoid.dll file and make sure it’s checked.

 If the custom functoid is deployed correctly, you can see it in the tool box as below:

 FunctoidToolBox1.GIF

 

 You can see the use of this functoid in the Map as below:

 

MapPic1.GIF

 

 

 Important: Note that you will have to add Microsoft.BizTalk.BaseFunctoids.dll in the project references.

 

ReferencesPic.GIF

Advertisements

Responses

  1. Hi
    Iam srinivas from Evantage Technologies as a SoftwareEngineer.
    Very good concept customfunctiod and pls any new topics in Biztalk server 2006 pls send my mail.

    Thanks & Regards,
    Srinivas K

  2. Hi
    i am nitish sikder.i am MS student.i am trying to implement b2b system by using biztalk server.if you have any topics or materials or b2b projects with biztalk 2006, please send me! it’s urgent.

    thanks with best regards,
    nitish sikder.

  3. Hello there, I’m Leandro, I hope you are alright and you are still working with Biztalk! ;).

    I’ve posted my Biztalk Custom Functoid Wizard in my blog, it’s pretty similar to the Adapter Wizard and Pipeline Component Wizard created by Scott, Boudewijn and Martijn.

    I hope you find it of use: http://www.leandrodg.com.ar/blog/2009/06/biztalk-functoid-wizard-for-biztalk-2004-2006/

    Cheers,
    Leandro.

    • Leandro,
      can you provide the link again for the wizard sourcecode download – the link on your website is a deadlink.
      thanks

  4. I want my Custom Functoid to connect to schema nodes as well as other functoids.It should be able to take input and output from schema nodes as well as from other functoids.
    I am not able to achieve it.I am not able to understand,which connectiontypes should I use ?Please help.
    I am using the below code in my Custom Functoid.

    this.SetMinParams(2);
    this.SetMaxParams(3);

    this.Category = FunctoidCategory.Unknown;
    this.OutputConnectionType = ConnectionType.All;
    this.AddInputConnectionType(ConnectionType.All);
    this.AddInputConnectionType(ConnectionType.All);
    this.AddInputConnectionType(ConnectionType.All);

  5. Online CC Checker Anonymous 2011 ==>> cordalis.0fees.net


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: