Custom Script Action - Authoring with the RCOM Gateway Script Language
Custom Script lets you add small, C#-like snippets (the RCOM Gateway Script Language) inside a workflow action to do transformations, calculations, and branching that would otherwise need lots of low-code blocks or are not yet possible with the currently available action blocks. It’s a curated C#-style wrapper: only platform-approved types, properties, and functions are available, compiled to .NET at save time. You pass the snippet as one static string in the action.
Quickstart (2 minutes)
-
Add the action
Open your workflow → Add Action → choose CustomScript. Paste your code into the action’s single Script field (static string). -
Use workflow variables directly
Inputs come from Event Processor variable mapping and earlier blocks. Assign your results back to the variables the next blocks will read. -
Run & inspect
Trigger the workflow. Use Job Logs to see each action’s start/end and View Context to inspect all variables after execution.
Example (paste into the Script field):
1EXAMPLE_DICTIONARY.Add("STATUS", "PROD");
2EXAMPLE_DICTIONARY.Add("LAST_SCAN", currentTimestamp);
3EXAMPLE_DICTIONARY.Add("LAST_SYNC", currentTimestamp);
4EXAMPLE_DICTIONARY.Add("LAST_DEVICE", deviceId);
5EXAMPLE_DICTIONARY.Add("LAST_INIT", null);
6EXAMPLE_DICTIONARY.Add("PROJECT", null);
7EXAMPLE_DICTIONARY.Add("EXPIRY_DATE", null);
8EXAMPLE_DICTIONARY.Add("SCAN_COUNTER", 0);What the CustomScript action is (and isn’t)
- Inline statements, not classes: a script is just a list of statements you write in the action; you don’t declare classes or methods.
- Strongly typed,
C#‑like syntax: semicolons, case‑sensitive identifiers, familiar control flow, and a safe subset of.NETinstance methods and properties. - Use it as “glue”: keep I/O (
DB,HTTP, object ops) in dedicated workflow actions; use scripts for transforms, validation, and branching helpers.
Where scripts get their data
-
Workflow variables populated by the Event Processor (via
Variable Mapping) and previous actions become your script’s inputs/outputs. You read and write them by name. (E.g., Variables, Lists, Dictionaries defined withSetVarAction.) -
Global/group variables are also available via the workflow’s runtime context.
You cannot define or create new variables within the Custom Script block. Use SetVar or SetDictionary actions to define variables, then use them in the custom script.
In practice, assign back into variables the later blocks will consume (e.g., set NormalizedId, IsValid, or update a Dictionary you pass forward).
RCOM Gateway Script Language: the essentials (C#-like, but slimmer)
Statement basics
- End statements with
;. - Whitespace/newlines don’t matter (write on one line or many).
- Use
{ ... }to group multiple statements into a single block.
1myInt = 20;
2myString = "hello";
3{
4 myInt = 20;
5 myString = "hello";
6}Assignment
Assign the result of an expression to a qualified ID (a variable or a property path that’s already defined):
1myInt = 15 * myInt; // variable
2Total = myOrder.Subtotal; // property
3myObj.A.B = 3; // nested propertyProperties must be writable; e.g., myString.Length is read-only.
Conditionals (if / else)
The condition must evaluate to bool.
1if (myInt < 10) myString = "ok";
2if (myInt == 5) {
3 myInt = myInt * 2;
4} else {
5 myInt = -myInt;
6}Loops (while, do..while)
1while (myInt < 5) {
2 myInt = myInt + 1;
3}
4do {
5 myInt = myInt + 1;
6} while (myInt < 5);foreach (iterate lists)
Works over List<T> where the declared type is assignable to T.
1foreach (int n in numbers) {
2 sum = sum + n;
3}
4foreach (string key in GetKeyList(myDic)) {
5 concat = concat + myDic[key];
6}Early loop control (continue, break)
1while (myInt < 5) {
2 if (myString == "ok") break;
3 if (myInt == 2) { myInt = myInt + 1; continue; }
4 myInt = myInt + 1;
5}Using continue/break outside a loop is a parser error.
Functions, methods, properties
You can call approved platform functions, either as stand-alone statements or capturing their return values.
1CastInt(myInt); // call as a statement
2myDate = DateTimeUtcNow(); // call as an expression that returns a valueYou can call:
| Function / Helper | Definition |
|---|---|
| DateTimeNow() | Returns the current system date and time. |
| DateTimeUtcNow() | Returns the current UTC (Coordinated Universal Time) date and time. |
| DateTimeOffsetNow() | Returns the current date and time with offset information (time zone aware). |
| NewGuid() | Generates a new globally unique identifier (GUID). |
| CastInt(obj) | Converts an object to an integer. |
| CastString(obj) | Converts an object to a string. |
| CastBool(obj) | Converts an object to a boolean (true/false). |
| CastDateTime(obj) | Converts an object to a DateTime value. |
| CastList(obj) | Converts an object into a list structure. |
| CastDictionary(obj) | Converts an object into a dictionary (key/value pairs). |
| GetKeyList(myDic) | Returns a list of keys (List<string>) from a dictionary. |
| String.PadLeft(10, "0") | Pads the string on the left with "0" until its total length is 10. |
| String.ToUpper() | Converts all characters in a string to uppercase. |
| String.Length | Returns the number of characters in a string. |
| String.SplitLength(string separator) | Returns the count of items when string is split by the separator. |
| String.SplitPart(string separator, int index) | Returns the part at the specified 0 based index after splitting by separator. |
| List.Count | Returns the number of elements in a list. |
| Object.ToString() | Returns the string representation of an object. |
| String.ToInt() | Converts a string to an integer. |
| String.ToGuid() | Converts a string into a GUID. |
| String.IsGuid() | Checks if the string is a valid GUID. |
| String.IsDateTime() | Checks if the string is a valid DateTime format. |
Only signatures involving supported base types are available; e.g., methods that require char or StringComparison are not exposed.
Types you can use
- Base:
string,int,long,double,decimal,bool,DateTime,DateTimeOffset,byte,Guid,object. - Collections:
List<T>,Dictionary<TKey, TValue>; can be nested (e.g.,List<Dictionary<string,object>>).
Identifiers, literals, comments, precedence
- Identifiers: letters/underscores to start; alphanumerics/underscore thereafter. Dot (
.) for member access. - Comments:
//single‑line,/* ... */inline. - Literals:
35,"text",0xA,.5,true,null. - Operator precedence mirrors
C#basics; parentheses override (e.g.,a*b + c,(a+b)*c;ANDbinds stronger thanOR).
Authoring workflow scripts step‑by‑step
- Drop action: Add
CustomScriptto your workflow. - Open form: Paste your source code into the
SCRIPTfield (static string). - Use existing vars: Reference mapped parameters and previous outputs directly by name.
- Assign outputs: Write results back into workflow variables (predefined variables) for downstream actions to consume.
- Save & test: Run an event through the workflow and inspect Job Logs and Context to verify values.
Best practices
- Keep scripts short and deterministic; prefer workflow actions for I/O and side effects.
- Guard nulls defensively:
if (x == null) x = ""; - Prefer extension/cast helpers over manual parsing; they validate and fail consistently.- Use
SplitLengthandSplitPartfor safe string splitting: check length before accessing a part to prevent index errors (e.g.,if (myString.SplitLength("/") >= 2) { ... SplitPart("/", 1) ... }).- Name variables clearly and avoidC#reserved keywords (the platform validates identifiers). - Use Job Logs + Context during testing to trace each action’s start/end and resulting variables; filter/download as needed.
Troubleshooting guide
| Symptom | Likely cause | Fix |
|---|---|---|
| Parser error near ';' | Missing semicolon / stray character | Check line endings; every statement ends with ;. |
| Unknown function or Unknown method | Calling a .NET API or a signature not exposed by Gateway | Replace with supported helper (.ToInt(), CastInt, PadLeft, etc.) or restructure. |
| Type mismatch | Expression returns the wrong type | Use Cast* helpers or change variable types/assignment. |
| Property is read‑only | Trying to set a read‑only member (e.g., myString.Length) | Assign to a variable, not to read‑only properties. |
| break/continue used outside loop | Control statement with no loop context | Only use inside while/foreach. |
| Script “runs” but outputs are empty | You didn’t assign back to workflow variables | Ensure that the variables the next action expects are written in the script. |
Reference: what’s officially supported in scripts
- Script usage & parameterization (action takes one static string, executes statement list).
- Statement basics (assignments, blocks, semicolons, whitespace).
- Assignment & qualified IDs (variables and writable properties).
- Conditionals (
if,if/else). - Loops (
while,do/while,foreach). - Loop control (
continue,break). - Function call statements and function‑call expressions; built‑in helpers; instance methods on supported base types; string extensions.
- Type system (base types + generic collections).
- Identifiers, literals, comments, precedence rules.