" MicromOne: Cancelling Save Events Based on Asynchronous Operation Results in Dynamics 365

Pagine

Cancelling Save Events Based on Asynchronous Operation Results in Dynamics 365


In Dynamics 365 model-driven apps, it's common to perform validations before saving a record. While synchronous validations are straightforward, asynchronous operations, such as server-side checks or API calls, introduce complexity. This article explores how to effectively cancel a save operation based on the outcome of an asynchronous process.(Microsoft Learn)

The Challenge with Asynchronous Validations

Traditionally, to prevent a save operation, developers use the preventDefault() method within the OnSave event handler:(Dreaming in CRM & Power Platform)

formContext.data.entity.addOnSave(function (e) {
    var eventArgs = e.getEventArgs();
    if (/* validation fails */) {
        eventArgs.preventDefault();
    }
});

However, this approach falls short when the validation involves asynchronous operations. For instance, consider a scenario where you need to check if a user with a specific phone number exists:(Dreaming in CRM & Power Platform)

formContext.data.entity.addOnSave(function (e) {
    Xrm.WebApi.retrieveMultipleRecords("systemuser", "?$filter=homephone eq '12345'")
        .then(function (result) {
            if (result.entities.length > 0) {
                e.getEventArgs().preventDefault();
            }
        });
});

In this case, the preventDefault() method is called after the asynchronous operation completes. However, by that time, the save operation may have already proceeded, rendering the prevention ineffective.(Stack Overflow)

A Workaround: Preemptive Save Cancellation and Conditional Resave

To address this, Andrew Butenko proposed a strategy where the save operation is initially canceled, and then conditionally retriggered based on the asynchronous validation result. Here's how it works:(xrmtricks.com)

  1. Cancel the Save Operation Immediately: Use preventDefault() at the beginning of the OnSave handler to halt the save process.(Microsoft Learn)

  2. Perform Asynchronous Validation: Execute the necessary asynchronous operations, such as API calls or data retrievals.

  3. Conditionally Resave: If the validation passes, programmatically trigger the save operation again.

Here's an implementation example:

formContext.data.entity.addOnSave(function (e) {
    var eventArgs = e.getEventArgs();
    eventArgs.preventDefault(); // Step 1: Cancel the save operation

    Xrm.WebApi.retrieveMultipleRecords("systemuser", "?$filter=homephone eq '12345'")
        .then(function (result) {
            if (result.entities.length === 0) {
                // Step 3: Resave if validation passes
                formContext.data.save();
            } else {
                // Validation failed; do not resave
                Xrm.Navigation.openAlertDialog({ text: "A user with this phone number already exists." });
            }
        });
});

Leveraging Asynchronous OnSave Handlers

With the introduction of asynchronous OnSave handlers in Dynamics 365, developers can now return a promise from the OnSave event handler, allowing the platform to wait for the asynchronous operation to complete before proceeding with the save.(Microsoft Learn)

To utilize this feature:

  1. Enable Async OnSave Handlers: In your app settings, navigate to Settings > Features and enable the Async OnSave handler option.(Microsoft Learn)

  2. Implement the Async Handler: Return a promise from your OnSave event handler. If the promise is resolved, the save proceeds; if rejected, the save is canceled.

Example:

formContext.data.entity.addOnSave(function (e) {
    return Xrm.WebApi.retrieveMultipleRecords("systemuser", "?$filter=homephone eq '12345'")
        .then(function (result) {
            if (result.entities.length > 0) {
                return Promise.reject(new Error("A user with this phone number already exists."));
            }
            return Promise.resolve();
        });
});

In this setup, if the validation fails, the promise is rejected, and the save operation is canceled automatically.


Handling asynchronous validations during save operations in Dynamics 365 requires careful implementation. By either preemptively canceling the save and conditionally resaving or leveraging the asynchronous OnSave handlers, developers can ensure data integrity and provide a seamless user experience.