Skip to content

Dynamics 365 WebAPI Asynchronous Calls

Dynamics 365 development is constantly evolving. One area that is always in flux is the JavaScript API. There are many exciting developments in the space like the introduction of WebApi’s method to allow basic CRUD operations (Link).

We no longer need to worry about including JSON files or calling jQuery libraries to make a simple API calls. The platform gives us simple methods to do basic CRUD operations.

Here is a simple example. I used the amazing REST Builder tool to generate the code. The code searches for an email address and returns the full name of the contact record.

function FindContactRecord(email) {
    Xrm.WebApi.online.retrieveMultipleRecords("contact", "?$select=fullname&$filter=(emailaddress1 eq '" + email + "')&$top=1").then(
        function success(results) {
            var result = results.entities[0];
            var fullname = result["fullname"];
            ProcessData(fullname);
        },
        function (error) {
            console.log(error.message);
        }
    );
}

The above code works great for a single record, since the ProcessData function gets invoked in the success function of the WebAPI call. When we start to do bulk operations, the code starts executing asynchronously. Here is an example of calling the function multiple times. This code is only for illustrations purposes. If we were to query multiple contact records, our best practice is to batch multiple email addresses into a single WebAPI call.

function FindContactRecords(EmailArray) {
    var contactFullnames = new Array();
    for (var i = 0; i < EmailArray.length; i++) {
        contactFullnames.push(FindContactRecord(email[i].trim()));
    }
    return contactFullnames;
}

function FindContactRecord(email) {
    Xrm.WebApi.online.retrieveMultipleRecords("contact", "?$select=fullname&$filter=(emailaddress1 eq '" + email + "')&$top=1").then(
        function success(results) {
            var result = results.entities[0];
            var fullname = result["fullname"];
            return (fullname);
        },
        function (error) {
            console.log(error.message);
        }
    );
}

//Main function 
var contactFullnames = FindContactRecords(EmailArray);
ProcessData(contactFullnames);

The main issue we face with the above code is that the contactFullname array will not return elements since JavaScript engine is executing the WebAPI calls asynchronously for performance reasons.

So how do we fix this problem? By using async, await and then statements, JavaScript will return a promise which will not execute subsequent code until the async code completes processing. The changes in blue illustrates the required changes.

async function FindContactRecords(EmailArray){
    var contactFullnames = new Array();
    for (var i = 0; i < EmailArray.length; i++) {
       await contactFullnames.push(FindContactRecord(email[i].trim()));
    }
    return contactFullnames;
}

async function FindContactRecord(email) {
    await Xrm.WebApi.online.retrieveMultipleRecords("contact", "?$select=fullname&$filter=(emailaddress1 eq '" + email + "')&$top=1").then(
        function success(results) {
            var result = results.entities[0];
            var fullname = result["fullname"];
            return (fullname);
        },
        function (error) {
            console.log(error.message);
        }
    );
}

//Main function 
FindContactRecords(EmailArray).then(
    contactFullnames => ProcessData(contactFullnames)
);

There are many articles that discusses async/await, but how to applies to Dynamics 365 is not something well covered. I hope thisĀ  article helps.

1 Comment

  1. Great post! We just ran into this issue today.

    Using async/await, you can also drop the .then() notation and have the result set to a variable directly. You should wrap it in a standard try/catch block still to catch any error that may occur. You can also use destructuring to have the resulting entities object aliased to contactRows.

    const { entities: contactRows } = await Xrm.WebApi.online.retrieveMultipleRecords(“contact”, …);


Add a Comment

Your email address will not be published.