Custom Actions
Custom actions extend the built-in action system with Low-Code C# implementations. This is relevant for Regulators at the Regulation Developer level — see No-Code and Low-Code Development for the full picture.
The workflow for creating a custom action: 1. Implement the case action in C# 2. Add the action to the regulation 3. Test the action 4. Use the action
In the following tutorial example, an action is created to validate the company ID. It is to be checked whether the checksum of the company ID complies with the ISO 7064 standard.
Case Action
The case action consists of metadata in the form of C# attributes and the implementation. For validation actions, errors are included with the AddIssue method.
namespace PayrollEngine.Client.Scripting.Function;
public partial class CaseValidateFunction
{
[ActionIssue("InvalidUId", "(0) with invalid UID: (1)", 2)] // register issue message
[ActionParameter("caseFieldName", "The case field name")] // register parameter
[ActionParameter("uid", "The UID text")] // register parameter
[CaseValidateAction("CheckUId", "Validate for the Swiss company id (UID)")] // register action
public bool CheckUId(string caseFieldName, string uid)
{
// extract check value
var checkValue = uid.RemoveFromStart("CHE-").Replace(".", string.Empty);
try
{
// ISO 7064 digit check with modulus, radix, character-set and double-check-digit option
new CheckDigit(11, 1, "0123456789", false).Check(checkValue);
return true; // valid UID
}
catch (CheckDigitException)
{
LogError($"Invalid Uid check value {checkValue}."); // optional log
AddCaseAttributeIssue("InvalidUId", caseFieldName, $"Invalid UId: {uid},");
}
return false; // invalid UID
}
}
You can also use the predefined digit checks
Mod11Radix2,Mod37Radix2,Mod97Radix10,Mod661Radix26,Mod1271Radix36.
Regulation Action
Next, the script with the validation function is included in the regulation:
regulations:
- name: ActionRegulation
lookups:
- name: MyActions.Actions # convention: ActionNamespace.Actions
values:
- key: InvalidUId
value: "(0) is invalid: (1)" # English issue message template
valueLocalizations:
de: "(0) ist ungültig: (1)" # localized German variant
cases:
- name: UId
caseType: Employee
defaultReason: Test UId
validateActions:
- "? CheckUId('UId', ^:UId)" # '?' = validate trigger; passes field name and value
fields:
- name: UId
valueType: String
timeType: Period
valueMandatory: true
defaultStart: today
attributes:
input.valueMask: CHE-000.000.000
input.valueHelp: Format CHE-123.456.789
scripts:
- name: MyActions
functionTypes:
- CaseValidate # binds C# file to the CaseValidate function type
valueFile: Scripts/CaseValidateFunction.cs
The lookups section registers the localized issue message under the convention ActionNamespace.Action (MyActions.Actions). The cases section defines the UId case field with the CheckUId validate action (see Action Syntax). The scripts section registers the C# file for the CaseValidate function type.
Action Test
The validation action UId is checked with the following test:
# yaml-language-server: $schema=../../Schemas/PayrollEngine.CaseTest.schema.json
testName: Test.UId
tenantIdentifier: ActionTenant
userIdentifier: lucy.smith@foo.com
employeeIdentifier: mario.nuñez@foo.com
payrollName: ActionPayroll
validateTests:
- testName: UId.Valid.999999996.Test # valid UID — expect value accepted unchanged
input:
userIdentifier: lucy.smith@foo.com
employeeIdentifier: mario.nuñez@foo.com
divisionName: ActionDivision
case:
caseName: UId
values:
- caseFieldName: UId
value: "999999996"
output:
values:
- caseFieldName: UId
value: "999999996" # value passes through unchanged
- testName: UId.Invalid.999999997.Test # invalid UID — expect CaseInvalid issue
input:
userIdentifier: lucy.smith@foo.com
employeeIdentifier: mario.nuñez@foo.com
divisionName: ActionDivision
case:
caseName: UId
values:
- caseFieldName: UId
value: "999999997"
output:
issues:
- caseFieldName: UId
issueType: CaseInvalid
number: 400 # HTTP 400 Bad Request
The first test (UId.Valid.999999996.Test) submits a valid UID value and expects it to be accepted unchanged in the output. The second test (UId.Invalid.999999997.Test) submits an invalid UID and expects a CaseInvalid issue with HTTP error code 400.
Command to execute the test:
PayrollConsole CaseTest Test.et.json
Action Usage
Finally, the validation also takes effect in the web application with a corresponding error message.
Next Steps
- No-Code and Low-Code Development — Regulator role overview and scripting functions
- Examples — payroll examples and demos
- Articles — blog posts and technical articles