Back to Errors and Warnings, Causes and solutions, this time with a surprising error that I got while I was testing a custom Functoid that I had developer: Extension function parameters or return values which have Clr type ‘Char’ are not supported
The full error description was:
Invoking component…
C:\Development\BizTalk Server Project1\BizTalk Server Project1\Map1.btm: warning btm1028: The required field “VarValue” has no incoming link, constant value, or default value.
TestMap used the following file: <file:///C:\Development\BizTalk Server Project1\Schema1_output.xml> as input to the map.
C:\Development\BizTalk Server Project1\BizTalk Server Project1\Map1.btm: error btm1050: XSL transform error: Unable to write output instance to the following <file:///C:\Users\Administrator\AppData\Local\Temp\2\_MapData\BizTalkServerProject1\Map1_output.xml>. Extension function parameters or return values which have Clr type ‘Char’ are not supported.
Test Map failure for map file <file:///C:\Development\BizTalk Server Project1\BizTalk Server Project1\Map1.btm>. The output is stored in the following file: <file:///C:\Users\Administrator\AppData\Local\Temp\2\_MapData\BizTalkServerProject1\Map1_output.xml>
Component invocation succeeded.
Again, I catch this error while I was trying to test my custom functoid inside Visual Studio.
The Custom Functoid was invoking the following code:
private string GetCSharpBuffer() { StringBuilder builder = new StringBuilder(); builder.Append("public string SplitText(string element, int pos, char splitter)\n"); builder.Append("{\n"); builder.Append("\tstring[] listValues = element.Split(splitter);\n"); builder.Append("\tif (listValues != null)\n"); builder.Append("\t\tif (listValues.Length &gt; pos)\n"); builder.Append("\t\t\treturn listValues[pos];\n"); builder.Append("\treturn \"\";\n"); builder.Append("}\n"); return builder.ToString(); }
Or, to be easier to read in a clean C# code that would be like this:
public string SplitText(string element, int pos, char splitter) { string[] listValues = element.Split(splitter); if (listValues != null) if (listValues.Length &gt; pos) return listValues[pos]; return ""; }
Cause
Unfortunately, this is a BizTalk mapper engine limitation. The type Char is not supported at least on built-in code inside the XSLT, in other words by using the Functoid SetScriptBuffer functionality:
SetScriptBuffer(ScriptType.CSharp, this.GetCSharpBuffer());
I didn’t test but it may work if you replace this functionality with the SetExternalFunctionName functionality:
SetExternalFunctionName(GetType().Assembly.FullName, GetType().FullName, "SplitText");
Note: This means that the code will not be inside the XSLT but instead you will be calling an external assembly that needs to be on GAC.
Solution
The simple solution, or let’s call I workaround, is to use strings instead, either on inputs as outputs parameters of the Functoid. For that we just need to replace the above code to this:
private string GetCSharpBuffer() { StringBuilder builder = new StringBuilder(); builder.Append("public string SplitText(string element, int pos, string splitter)\n"); builder.Append("{\n"); builder.Append("\tstring[] listValues = element.Split(Convert.ToChar(splitter));\n"); builder.Append("\tif (listValues != null)\n"); builder.Append("\t\tif (listValues.Length &gt; pos)\n"); builder.Append("\t\t\treturn listValues[pos];\n"); builder.Append("\treturn \"\";\n"); builder.Append("}\n"); return builder.ToString(); }
Or again, in a simple C# form:
public string SplitText(string element, int pos, string splitter) { string[] listValues = element.Split(Convert.ToChar(splitter)); if (listValues != null) if (listValues.Length &gt; pos) return listValues[pos]; return ""; }
By doing that you will be able to successfully test the Functoid.