1 minute read

With v9 a lot of changed. One of the major changes is client web API, some of calls were made deprecated and some were added. For example, Xrm.WebApi.

The new ‘Xrm.WebApi.retrieveRecord(entityLogicalName, id, options).then(successCallback, errorCallback)’ can’t be made synchronous. But imagine situation, in which you need to go through multiple entities (lookups). In this scenario, you need the result of retrieved record to access the next record. So how can this be done?

In this case, you need to use successCallback, which can be nested – so you can go through multiple entities:

Xrm.WebApi.retrieveRecord(entityLogicalName, id, options)
    .then(function(x) {
       return Xrm.WebApi.retrieveRecord(x.lookupEntityLogicalName, x.lookupValue, options)
    }, errorCallback)
    .then(function(y) {
        return Xrm.WebApi.retrieveRecord(y.lookupEntityLogicalName, y.lookupValue, options)
     }, errorCallback)
     .then(function(z) {
        return Xrm.WebApi.retrieveRecord(z.lookupEntityLogicalName, z.lookupValue, options)
     }, errorCallback)

But if you are like me, you probably already found this out on your own. What’s the issue with this solution? You don’t want to nest calls to targeted record in advance, you want to specify path to this record and what should be done with the result. So, you can use the same code snippet.

I wrote simple recursion function that does exactly what’s described above. This may be exactly what you were looking for:

function createRetrieveRecordPromise(entityLogicalName, entityId, pathToEntity, finalFunction, depth = 0) {
    Xrm.WebApi.retrieveRecord(entityLogicalName, entityId).then(
        function success(result) {
            if (depth < pathToEntity.length) {
                entityLogicalName = result[`_${pathToEntity[depth]}_value@Microsoft.Dynamics.CRM.lookuplogicalname`];
                entityId = result[`_${pathToEntity[depth]}_value`];
                createRetrieveRecordPromise(entityLogicalName, entityId, pathToEntity, finalFunction, depth);
            else {
        function (error) {

// example call
    ["quoteid", "customerid"],
    function (lastRecord) {

I will write something more advanced next time, no worries.


Jan Kostejn

Hello Andrew, you are absolutely right. We were discussing this with my colleagues and choose this option because of the limitation to one expand on retrieveMultipleRecords call. But what I didn’t considered is FetchXML query instead of OData query. I haven’t tested it, but it should work.

So thanks for the comment.

We use this method, because I think it’s more pleasant for the customizers of Dynamics Solutions.

When I get a little more time, I’ll try to edit the post with your input.

Thanks again.


Can I access response outside of thebelow method.Like I want to access the result globally Xrm.WebApi.online.retrieveRecord(“new_roombooking”, “00000000-0000-0000-0000-000000000000”, “null”).then( function success(result) { var new_roombookingid = result[“new_roombookingid”]; }, function(error) { Xrm.Utility.alertDialog(error.message); } );Xrm.WebApi.online.retrieveRecord(“new_roombooking”, “00000000-0000-0000-0000-000000000000”, “null”).then( function success(result) { var new_roombookingid = result[“new_roombookingid”]; }, function(error) { Xrm.Utility.alertDialog(error.message); } );

To submit comments, go to GitHub Discussions.