Canvas App showing loading icon on Dynamics 365 CE forms – Power Platform

Hi Everyone,

Today I was working on simple Canvas App and I have to show it on Model Driven Form on Dynamics 365 CE. I have published the Canvas App, copied the URL and did set to the IFrame on the form. Here is the configuration of the same.

I have saved the Form, Published and navigated to the Account page. To my surprise, it started showing only loading icon.

I was thinking something going at the Canvas App side but when I play, it is working fine. Came to the conclusion that certainly some thing from Dynamics side is blocking the content. And finally, it is Cross-frame Script which is blocking the content. After un-checking “Restrict cross-frame scripting, where supported. ” checkbox everything started working.

Hope this helps.


Happy 365’ing
Gopinath.

Set Canvas App URL on Dynamics 365 CE – Power Platform

Hi Everyone,

Today I was talking to one my friends on the deployment of Canvas Apps that were configured as an IFrame on Model Driven Forms of Dynamics 365. The problem with this is, every time deployment happens the URL would be overridden and we have to manually open the properties of IFrame to set it to the right one.

We can write JavaScript to retrieve the URL from some configuration/setting entity but every time, the call would be executed which we don’t want. Here comes our friend Session Storage to help use.

We have added the piece of code to set the URL that is retrieved as Session Storage item and using it to setSrc instead of retrieving Settings/Configuration record every time. In fact, this solution all configurations whatever we are retrieving, we can use SessionStorage or LocalStorage based on the scenario which will eventually reduces the calls from client side and hence improves the performance.

The only you should remember is to use Unique Name for the session variable, I normally use combination of OrganizationID and Configuration name.

Here is the code for your reference. First checking for the value in the Session Storage and if it contains value, taking it from there otherwise retrieve it and set to IFrame src as well as SessionStorage item with unique name to use next time.

function setCanvasAppsURL(executionContext, controlName, ConfigName) {
    var organizationSettings = Xrm.Utility.getGlobalContext().organizationSettings;
    var formContext = executionContext.getFormContext();
    var sessionVariable = organizationSettings.organizationId + ConfigName;
    var sessionVariableValue = sessionStorage.getItem(sessionVariable);
    var url = null;
    if (ConfigName != null && sessionVariableValue == null) {
        ///Get config value from configuration
        var globalContext = Xrm.Utility.getGlobalContext();
        var parameters = {};
        parameters.ConfigName = ConfigName;
        var req = new XMLHttpRequest();
        req.open("POST", globalContext.getClientUrl() + "/api/data/v9.1/SettingsEntity", true);
        req.setRequestHeader("Accept", "application/json");
        req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        req.setRequestHeader("OData-MaxVersion", "4.0");
        req.setRequestHeader("OData-Version", "4.0");
        req.onreadystatechange = function () {
            if (this.readyState == 4) {
                req.onreadystatechange = null;
                if (this.status == 200 || this.status == 204) {
                    if (JSON.parse(this.response).ConfigKey != null) {
                        url = JSON.parse(this.response).ConfigKey;
                        if (url != null) {
                            if (formContext.getControl(controlName) != null && formContext.getControl(controlName) != undefined) {
                                formContext.getControl(controlName).setSrc(url);
                                sessionStorage.setItem(sessionVariable, url);
                            }
                        }
                    } else {
                        console.log("Error"); 
                        Xrm.Utility.closeProgressIndicator();
                        var alertStrings = {
                            confirmButtonLabel: "Ok", text: "Error : " + JSON.parse(this.response).error.message
                        };
                        Xrm.Navigation.openAlertDialog(alertStrings);
                    }
                }
            }
        };
        req.send(JSON.stringify(parameters));
    }
    else
    {
        formContext.getControl(controlName).setSrc(sessionVariableValue);
    }
}

Hope this helps.


Happy 365’ing
Gopinath