Skip to main content

PreCreate Trigger

  • PreCreate Trigger programs are executed while a new Protrak Type Instance is created, before the platform code for instance creation executes.
  • They are used to validate or manipulate the instance details based on business requirements.
  • They are executed synchronously, i.e. in the same transaction as the instance creation.
  • They are executed before standard validations like name/ trackingId uniqueness validations are executed by the platform code.

Coding guidelines

  • PreCreate Trigger program is a class that must implement the interface IPreCreateTriggerProgramAsync

    public interface IPreCreateTriggerProgramAsync
    {
    Task<ProgramResult> RunAsync(Instance instance);
    }

    NOTE: Implement IPreCreateTriggerProgramAsync with the RunAsync method to enable asynchronous, scalable trigger logic. Most internal service methods are now async, and their synchronous versions are deprecated and will be removed. Use RunAsync to ensure compatibility with these changes.

  • Protrak runtime passes Instance object having information about the instance being created to the trigger. This object can be modified by the program code (pass by reference).

    • The instance attribute values contain values passed to the service (typically values entered by user in the create form or those passed to the POST request) and default values configured at attribute level, as applicable.
  • Program should return a ProgramResult object:

    • If IsSuccess is true, then the trigger execution is considered as successful.
    • If IsSuccess is false, then the trigger is considered as failed, subsequent code is not executed, and the DB transaction is rolled back.
    • If IsSuccess is false, ideally the string[] Errors should be populated with proper error messages which will be returned in API response, which can be displayed to end user.
  • As the trigger is executed before platform validations, the instance details may not have all valid data. For examples, all mandatory attributes may not be populated. While writing the program code, do not assume that all data will be valid. Write guard conditions to avoid runtime exceptions.

Typical use cases for PreCreate Trigger

  • Validate the instance being created where some complex business logic is involved.
  • Calculate and save an attribute value on the instance being created using complex business logic. Use program trigger when the computation is not possible using expression attribute or using an expression attribute is not possible for some reason.
    • For example, when business logic involves fetching related instance details from reference attribute and using those details for some computations.
  • If any validations or calculations need to use a third-party service or integration.

Anti-patterns or when not to use PreCreate Trigger

  • Prefer configuration over customization. Avoid using a program when configurable validations or computations are possible, for example. using expressions in sequence code or using expression attributes.
  • Do not use PreCreate trigger to make changes that are not reversible, like sending an email. If the create process fails, the transaction will be rolled back, instance will not be visible but the email would have been sent already!

Sample Code

public class ProjectPreCreateTriggerProgram : IPreCreateTriggerProgram
{
public ProgramResult Run(Instance instance)
{
var errorMessages = ValidateProject(instance);
if (errorMessages.Length == 0)
{
return new ProgramResult() { IsSuccess = true, Errors = null };
}
else
{
return new ProgramResult() { IsSuccess = false, Errors = errorMessages };
}
}

private string[] ValidateProject(Instance instance)
{
var startDate = instance.Attributes.FirstOrDefault(a => a.Name == ATTRIBUTE_START_DATE);
//validation code here
return new string[] {};
}
}

Note: The Run method (from IPreCreateTriggerProgram) should only be used if the trigger logic is fully synchronous, does not involve any service/API calls, and consists only lightweight in-memory operations.