We recently encountered a scenario where some JavaScript was no longer working after the Dynamics 365 environment was upgraded to the UCI. We started debugging and soon found that our JavaScript callback code handling the response of a custom action was no longer working.
The guilty code
The snippet below is the old JavaScript callback code that handled the response coming from the custom action.
Xrm.WebApi.online.execute(thr_DownloadMultipleInvoicesRequest).then( function success(result) { if (result.ok) { var results = JSON.parse(result.responseText); var base64ZIP = results.Base64ZIPFile; if(base64ZIP) { download("data:application/zip;base64," + base64ZIP, "Invoices.zip", "application/zip"); Xrm.Utility.closeProgressIndicator(); } else { Xrm.Utility.closeProgressIndicator(); Xrm.Utility.alertDialog("No invoices found."); } } else { Xrm.Utility.closeProgressIndicator(); Xrm.Utility.alertDialog("Unknown error occured in ISV code."); } }, function(error) { Xrm.Utility.closeProgressIndicator(); Xrm.Utility.alertDialog(error.message); } );
However, where as this used to work perfectly fine in the ‘old’ UI, it now crashed on the “JSON.parse(result.responseText)”. The reason for this is that the responseText was not returned from the custom action. Being the developers we are, we opened up our Chrome Developer Tools and dug a little deeper into the issue.
What we noticed here, is that there is indeed no responseText avaiable. Even more importantly, the body property is a ReadableStream. This immediately rang a bell, and made us think of the new Fetch API. (Yes, for Dynamics 365 developers having a Fetch API is wildly confusing :-)).
Fetch API
The Fetch API acts as a replacement for the former XMLHttpRequest and offers a lot of benefits compared to the latter. Without going in details about the what and how, I strongly encourage you to read Jake Archibald’s blog post regarding the API.
For those of you who are thinking ‘what the f$#k whas wrong with XmlHttpRequest’, Jake summarizes it as follows:
“XHR was an ugly baby and time has not been kind to it. It’s 16 now. In a few years it’ll be old enough to drink, and it’s enough of a pain in the arse when it’s sober.”
Although it’s not explicitely mentioned, you can find a sample of this new Fetch API based way of working in the Microsoft Docs page about the Xrm Web API Methods.
So… The solution please?
So long story short, how do we solve this? We need to change the way we read data from the request, by treating the response as a stream. Below is the final JavaScript callback code.
Xrm.WebApi.online.execute(thr_DownloadMultipleInvoicesRequest).then( function success(result) { if (result.ok) { result.json().then(function(results) { var base64ZIP = results.Base64ZIPFile; if (base64ZIP) { download("data:application/zip;base64," + base64ZIP, "Invoices.zip", "application/zip"); Xrm.Utility.closeProgressIndicator(); } else { Xrm.Utility.closeProgressIndicator(); Xrm.Utility.alertDialog("No invoices found."); } }); } else { Xrm.Utility.closeProgressIndicator(); Xrm.Utility.alertDialog("Unknown error occured in ISV code."); } }, function(error) { Xrm.Utility.closeProgressIndicator(); Xrm.Utility.alertDialog(error.message); } );
Hope this helps anyone out there!
Thanks a lot nathan. this is what i was looking for. it solved my problem.
Thanks nathan, i was looking such solution from long time and i got your solution and it's worked for me. keep sharing your knowledge.