Async onSave preventDefault with external call

One of our current projects is the migration of an onPrem Dynamics 365 to the Cloud. Part of that is refactoring existing JavaScript implementation. The current implementation had an onSave function which prevented the save process based on a call to the WebAPI. It took me some time to migrate the function, therefore I thought it might be interesting for others to know how to write an async onSave preventDefault with external call.

Background

All calls to the WebAPI (through Xrm.WebApi) are done async in the Power Platform. This means if you need to get additional data to determine whether you would like to cancel the current save event you would need an async onSave.

I tried the usual approach of calling “preventDefault“, which did not give the expected result as the save was executed either way. According to the Microsoft documentation you should in that case use preventDefaultOnError instead of preventDefault.

Cancels the save operation if the event handler has a script error, returns a rejected promise for an async event handler or the operation times out.

MS Learn

This means the preventDefaultOnError function expects a promise which should either result in success or be rejected. Doing an “await” on the call to the Xrm.WebApi will not cancel the save event.

Configure Model-Driven App

Before we go to deep into the implementation and the JavaScript code we have to configure our Model-Driven App to use aync onSave events.

To activate the async onSave handler feature you have to edit the Model-Driven App, go to settings, Features and activate the “Async save handlers” feature.

Open MDA Settings
Activating Async save handler

Implementation

Let’s take a look at the implementation. Here is a simple onSave function which prevents saving when there is no account with the name “Benedikt”(both in TypeScript and JavaScript).

TypeScript
async function onSave(eventContext: Xrm.Events.EventContext): Promise<void> {
(eventContext as Xrm.Events.SaveEventContext).getEventArgs().preventDefaultOnError();
return new Promise(async (resolve, reject) => {
try {
await Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name&$filter=name eq 'Benedikt'");
resolve();
} catch (error) {
console.log(error);
reject(error);
}
});
}
JavaScript
async function onSave(eventContext) {
eventContext.getEventArgs().preventDefaultOnError();
return new Promise(async (resolve, reject) => {
try {
await Xrm.WebApi.retrieveMultipleRecords("account", "?$select=name&$filter=name eq 'Benedikt'");
resolve();
}
catch (error) {
console.log(error);
reject(error);
}
});
}

First of all, we do execute the preventDefaultOnError function. As I mentioned this function expects a promise to be rejected (or timed out) to prevent the save.

That is the reason why we return a promise where in we make our request to the WebApi (or any other service you’d like to). The promise get’s resolved when there is more than one result. In any other case (no result or error) it gets rejected and therefore the save of the form is cancelled.

Conclusion

I hope you learned how to create an async onSave preventDefault with external call. When you understand what the function preventDefaultOnErrror expects, it is not very hard to satisfy it.

Please let me know if you have any questions or feedback.

This is just 1 of 60 articles. You can browse through all of them by going to the main page. Another possibility is to view the categories page to find more related content.
You can also subscribe and get new blog posts emailed to you directly.
Enter your email address to receive notifications of new posts by email.

Loading
2 Comments
  1. Avatar

Add a Comment

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