How to use Promise to evaluate your ribbon enable rules with asynchronous Xrm.WebApi methods in Dynamics 365 Unified interface.

We all have been using Xrm.WebApi methods isn’t it? After all why not? They are wonderful. You no longer need to write lengthy XmlHttpRequests and parse the raw JSON results back. Xrm.WebApi methods does the hard part of converting the raw JSON outputs into strongly typed objects.

Not sure if anyone is still there but if you are new to Xrm.WebApi methods, below is the perfect link to get you started.

https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/xrm-webapi

Just when you are about to think that Xrm.WebApi methods have successfully ticked all the boxes, comes the ribbon rules. Xrm.WebApi rules are asynchronous.

Suppose you have a requirement where you need to show a ribbon button only if user is in role of Salesperson. For that we write one function “userHasRole” with the code below

 function userHasRole() {

       var isUserAdmin = false;

        Xrm.WebApi.retrieveMultipleRecords("role", "?$select=roleid&$filter=name eq 'salesperson'").then( 
            function success(result) { 
                 var userSettings = Xrm.Utility.getGlobalContext().userSettings; 
                var securityRoles = userSettings.securityRoles;

                var isUserAdmin = false; 
                 for (var i = 0; i < result.entities.length; i++) { 
                     var roleId = result.entities[i].roleid;

                    if (securityRoles.indexOf(roleId) !== -1) { 
                         isUserAdmin = true; 
                        break; 
                    } 
                } 
            }, 
            function (error) { 
                console.log(error.message); 
            } 
         );

return isUserAdmin; 
}

The problem with this code is very evident. Before Xrm.WebApi return the results, the function would return false. Off course you can modify this function using window level objects and then using Xrm.Page.ui.refreshRibbon() to refresh the ribbon after Xrm.WebApi returns results. And perhaps we all have done that so far.

While the above method would certainly work, you may think like – “Is this the only way?” Certainly not. If you are using Unified interface (only option left for online users after Oct 2020), you have a better way to achieve the same. Unified interface rules support returning a Promise rather than boolean for asynchronous rule evaluation. Let’s see how we can re-write the same rule using Promise. And surprisingly, many of us working in Dynamics 365 day in and day out are not aware of this.

function userHasRole() { 
    return new Promise(function (resolve, reject) {

        Xrm.WebApi.retrieveMultipleRecords("role", "?$select=roleid&$filter=name eq 'salesperson'").then( 
            function success(result) { 
                var userSettings = Xrm.Utility.getGlobalContext().userSettings; 
                var securityRoles = userSettings.securityRoles;

                var isUserAdmin = false; 
                for (var i = 0; i < result.entities.length; i++) { 
                    var roleId = result.entities[i].roleid;

                    if (securityRoles.indexOf(roleId) !== -1) { 
                        isUserAdmin = true; 
                         break; 
                    } 
                 }

                // return true or false 
                resolve(isUserAdmin); 
            }, 
            function (error) { 
                reject(error.message); 
                console.log(error.message); 
            } 
        ); 
    }); 
}

Not much change in the code. All you need to do is return a Promise the resolve method of which should return true or false depending on business logic. And one very important to remember is that not only with Xrm.WebApi methods but also if you are using XMLHttp async, it would work just fine.

Put your code within the Promise and everything works like charm.

Any functionality before we implement, we should be aware of the limitations of the same. So we have a couple of them here.

  • This only works for Unified Interface. If you are using WebClient this won’t work
  • If the rule does not evaluate within 10 seconds, the rule would resolve with false value

Before I end, you may be asking where should can I find this in Microsoft documentation. Well if you are a big fan of Microsoft docs like me, here you go – https://docs.microsoft.com/en-us/dynamics365/customerengagement/on-premises/developer/customize-dev/define-ribbon-enable-rules#custom-rule

Hope this helps!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit www.xrmforyou.com or reach out to us at info@xrmforyou.com

Our product offerings:

Role based views for Dynamics 365 (http://www.xrmforyou.com/role-based-views.html)

CRM-Sharepoint Attachment uploader and metadata manager (http://www.xrmforyou.com/sharepoint-integrator.html)

Record Cloner for Dynamics 365 (http://www.xrmforyou.com/record-cloner.html)

Multiselect picklist for Dynamics 365 (http://www.xrmforyou.com/multi-select-picklist.html)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s