The Scripting functoid enables you to use Inline Custom Script (C# .NET, JScript .NET, Visual Basic .NET, Extensible Stylesheet Language Transformations (XSLT) or XSLT Call Template) or call code from an external assembly at run time to perform operation otherwise not available through built-in Functoids. For example, using Scripting functoid with Inline C# is convenient for creating a custom operation that you are unlikely to use elsewhere in your application or other maps.
In one of my previous posts, “BizTalk Mapper tips and tricks: How to reuse Scripting Functoids with Inline C# inside the same map”, I addressed and explained the main reasons why developers should use the Scripting Functoid, being:
There are also some precautions you need to take care of when using, or reusing the same Custom Inline C# scripts inside the Scripting Functoid, namely:
Developers use several unusual approaches to accomplish the reuse of Scripting Functoids inside the BizTalk Mapper, approaches that I call “Reusing in a Bad Way” and “Reusing in a Crazy Way”. At the end of the post, I explained which was the best way to reuse Scripting Functoids with inline C# using a very simple scenario.
In my opinion, the solution provided in my post is still the best option. However, it can also provide some challenges in terms of maintenance and development, that I will be addressing in this article.
Let’s imagine a scenario identical to what I used in the previous post, but with some differences in the source and destination schemas. And for this demo purpose, we will have:
public string FormatDate(string inputDate, string inputFormat, string outputFormat) { System.DateTime date; if (System.DateTime.TryParseExact(inputDate, inputFormat, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AssumeLocal, out date)) { return date.ToString(outputFormat); } return ""; }
public string ChangeDecimalSeparator(string inputDate) { return inputDate.Replace(",","."); }
According to my previous post, we will have something like this:
In the first Scripting Functoid, we will have to specify the body function and in the second functoid, only the function declaration (without the body). Actually, it doesn’t matter if it is the first or the second — the point is that in one of them you need to have the body of the function and the others you just need the function declaration.
So, what is “wrong” with this approach? Or better, what are the limitations of this approach?
Well, nothing is wrong with this approach. However, it has some limitations that you need to be aware of:
For these limitations, this approach can be, or become, a problem in some scenarios in terms of:
Knowing all this, the main question is: How can we improve this approach in a way that we can solve all of these limitations?
After considering several approaches, keeping in mind that the purpose here is to maintain the use of Inline C# Scripting Functoids (not changing to approaches that use external Assemblies or Custom Functoids), I thought that the ideal solution would be to create a concept of Global Functions that I could use them anywhere within my map but, having a unique place with quick and easy access where I can maintain the code.
To create the concept of Global C# Functions that you can use inside your maps, you need to:
public string FormatDate(string inputDate, string inputFormat, string outputFormat) { System.DateTime date; if (System.DateTime.TryParseExact(inputDate, inputFormat, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AssumeLocal, out date)) { return date.ToString(outputFormat); } return ""; }
Now you can use these functions in other grid pages using only the function declaration:
public string FormatDate(string inputDate, string inputFormat, string outputFormat)
or
public string ChangeDecimalSeparator(string inputDate)
However, if you try to compile or test the map, you will see that there will be some errors and your map will not work. The same “Unable to write output instance to the following <…>. ; expected” error that we already saw above.
To solve this error and to be able to create the concept of Global Functions you need to:
This should do the trick. Now if you compile or test your map everything will work.
You can find all the source code here: BizTalk Mapper Tips and Tricks: How to create a Global Inline C# Function