Tips For Avoiding Issues With Presaveitem And Presaveaction

What PreSaveItem and PreSaveAction Do

The PreSaveItem and PreSaveAction interfaces in Microsoft Dynamics 365 allow developers to customize business logic that executes prior to saving records in the system. PreSaveItem executes logic before saving individual record updates, while PreSaveAction allows logic to run before bulk save operations.

Using these interfaces correctly is critical to avoid unexpected errors and ensure proper data integrity. However, developers can run into issues if best practices around data types, asynchronous execution, infinite loops, and other areas are not followed.

Common Causes of Issues

Invalid Data Types

One frequent cause of errors in PreSaveItem and PreSaveAction plug-ins is incorrect data types being used for input parameters or return values. For example, if an integer is expected but a string is provided, runtime errors will occur. Being mindful of the expected data types for context parameters like Target and PostEntityImages can prevent data issues and exceptions.

Asynchronous Execution

By default, plug-ins executing PreSaveItem or PreSaveAction run asynchronously by queueing the logic in the system job framework. This can cause unexpected results if the saved data is accessed later in the transaction. Developers should leverage the SynchronousExecutor if context data needs to be referenced after the save event, or design asynchronous jobs carefully to avoid race conditions.

Infinite Loops

Logic errors in recursive calls between plug-ins and workflow can result in infinite loops, causing server crashes or extreme slowness. This is a rare issue but important to safeguard against by having exit conditions for loops and testing complex cascading logic thoroughly.

Best Practices

Validate Input Data

Performing checks on the data types and contents of input parameters and entity images in PreSaveItem and PreSaveAction plug-ins is highly recommended. This catches bad data earlier in the process and allows easier diagnosing of issues. Example input validations include checking for null values, validating parameter types, and verifying IDs reference existing records.

Use Synchronous Execution When Possible

While asynchronous execution has advantages for long-running processes, synchronous execution reduces complexity and ensures saved data persists properly when later referenced. Utilize the SynchronousExecutor class for PreSaveItem and PreSaveAction logic where possible, and limit asynchronous jobs to events requiring background processing.

Include Exit Conditions for Loops

Infinite recursion and loops can freeze the platform so have clear exit conditions, especially when executing recursive plug-in calls. Example exits include maximum iteration counts, validating for null values, and checking flags to end processing. Unit test complex cascading logic to detect endless loops or unintended recursion early.

Example Code Snippets

Data Type Checks

“`
// Verify parameter types
if (context.Depth != (int)context.Depth
|| context.PreEntityImages == null
|| context.PostEntityImages == null)
throw new InvalidPluginExecutionException(“Invalid parameter types.”);

// Check for null record ID
if (context.PrimaryEntityName == null)
return;
“`

Wrapping in SynchronousExecutor

“`
// Enforce synchronous execution
var executor = new SynchronousExecutor();
executor.Execute(context =>
{
// Plugin logic here
});
“`

Loop with Counter

“`
// Include max iterations with recursive call
const int MAX_LOOPS = 100;
int counter = 1;

while(counter < MAX_LOOPS) { // Logic here if (exitConditionMet) break; counter++; } ```

Debugging Techniques

Logging and Tracing

Incorporating logging statements and enabling system tracing allows recording of key debug information like parameter values, data changes, and exception details. This information captured in log files simplifies diagnosis of issues occurring in production plug-in executions.

Using Debug Mode

Visual Studio and other IDEs have powerful debuggers to step through plug-in logic line-by-line. Leverage debug mode with breakpoints set to identify problems in your PreSaveItem and PreSaveAction code before packaging and releasing updates.

Checking Correlation IDs

Every plug-in execution associated with a specific call chain shares the same correlation ID value. Tracking this ID in logs across events provides insight into cascading execution order and performance profiling. Note correlation IDs can change between synchronous and asynchronous runs.

Additional Resources

For further guidance on PreSaveItem, PreSaveAction and other plug-in best practices consult the following:

Leave a Reply

Your email address will not be published. Required fields are marked *