User Review
( votes)Introduction:
I am sure you may have used OnSave event several times in your projects. We generally use this event and write code in it to do some validation on record to restrict the user from saving the record (using prevenDefaults method).
The nature of OnSave event is synchronous. It is not right to call it asynchronous code because it does wait for it and we may see unsaved changes. If we make synchronous network request in OnSave event, it can cause slow experience and unresponsive page.
Microsoft has introduced a new aysnc OnSave event. This event is called after save event is complete and it supports after Save actions when the save event is successful or failed. There is also a new timeout if the promise does not resolve within 10 seconds. If it does not resolve within 10 seconds, the save operation will be blocked.
We will see how this async event is useful over save event. To enable this feature we need to create one record in Model driven app settings.
To enable the AsyncOnSave for a specific app, add the below XML in the customization.xml file. This should be added in the existing App Module node in your customization.xml file.
Setting the <value>true</value> enables AsyncOnSave support for that specific app.
<appsettings>
<appsetting uniquename="CRMHub_SalesApp_AsyncOnSave">
<iscustomizable>1</iscustomizable>
<settingdefinitionid>
<uniquename>AsyncOnSave</uniquename>
</settingdefinitionid>
<value>true</value>
</appsetting>
</appsettings>
Import this into Dynamics 365 CRM.
Once appsettings is added, you can check whether the feature is enabled or not, as shown below – (Value should be True).
Now, given below is the code for Async on save –
onLoad(executionContext): void {
let functionName: string = "onLoad";
try {
let formContext = executionContext.getFormContext();
formContext.data.entity.addOnSave(
(() => {
return async (context) => {
context.getEventArgs().preventDefaultOnError();
await AfterSaveAsyncMethod(context);
}
}
)());
var AfterSaveAsyncMethod = (context) => {
return new Promise((resolve, reject) => {
Xrm.WebApi.retrieveMultipleRecords("contact", "?$select=fullname&$filter= emailaddress1 like '%gmail.com%'")
.then(function (result) {
if (result.entities.length>0) {
resolve(true);
}
else {
reject("error");
}
});
});
}
}
catch (ex) {
Xrm.Navigation.openErrorDialog(ex.message).then(
function (success) {
console.log(success);
},
function (error) {
console.log(error);
});
}
}
In the above code, you can see that I have registered the save event on a load of form. The OnSave event can now accept promises. And when you return a promise inside your method registered on save of the form, it becomes async.
I have called Xrm.WebApi.retrieveMultipleRecords which is async method, because of which save event will wait until retrieve is completed. Here, to cancel the save operation, I tried to use executionContext.getEventArgs().prevenDefault(). But this did not work because Microsoft has added Context.getEventArgs().preventDefaultOnError() method for async OnSave restriction.
You will get the below error if promise didn’t return within 10 seconds –
One more thing I want to highlight is if Context.getEventArgs().preventDefaultOnError() method is called, then the Async OnSave event will still wait for all the promises to settle, but the save will not occur. This means the logic in it will still execute successcallback and errorcallback.
Conclusion:
In this way, you can easily use the Async OnSave event in Dynamics 365 CRM.
Reference Link: https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/events/form-onsave