Dynamics Ninja Logo

Blog.

How to embed Forms Pro in Dynamics 365

Cover Image for How to embed Forms Pro in Dynamics 365
·
6 min read

Introduction

It's been a while since Forms Pro became available as a public preview and I must say that I fell in love with them when I saw them for the first time. From the very first moment, I was thinking how can I use them inside Dynamics 365 interface.

There are 3 types of embedded controls for Forms Pro:

  • Inline
  • Pop-up
  • Button

The first one that got my attention was Pop-up because I thought that it might serve me as a dialog (happily after old dialogs became deprecated). Sadly that option disappointed me really fast because of CORS (Cross-Origin Resource Sharing). When you make a ribbon button/field event that will call a simple function for showing pop-up you will get a CORS warning in the console and nothing will happen in the end.

The problem is in the authentication that is posting to the microsoft.com domain and not to the dynamics.com so there is no way of making it work in any kind supported manner.

Cross-Origin Read Blocking (CORB) blocked cross-origin response https://web.vortex.data.microsoft.com/collect/v1?$mscomCookies=false&ext-javascript-msfpc=%27GUID%3Dbb5c8a44823b499cb112d9c7978b1e89%26HASH%3Dbb5c%26LV%3D201904%26V%3D4%26LU%3D1556556504179%27 with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details. 

The same thing happens if you try to call other to type (Inline and Button) of embedded controls from the ribbon or form event.

The only way to overcome CORS limitation is to put the code into the IFRAME and invoke the code inside of it, but let's make it more useful by putting the Dynamics form context to the survey response.

Goal

Our goal for this one will be to create a survey for the contact form. The survey will have 2 questions about customers satisfaction with some CRM product. We will concatenate those answers to one string, update the survey response record (activity entity), set regarding to the contact and finally show it in the Timeline on the contact form.

Solution

The first thing we need to do is to create our survey that will be showed on the contact form.

First question will choice between 3 answers:

  • Salesforce
  • Dynamics 365
  • Zoho

Second question will be just a rating one that will hold values 1-5.

Next step is the Send Survey tab in which we need to choose an Embed option. Since we will do it on the form inside an IFRAME the best option here is to choose Inline.

Since it will be embedded on the contact form we need to create a custom parameter that will hold id of the contact.

After adding the custom parameter it's time to press generate code button. You will get something like this:




    function renderSurvey(parentElementId, contactId) {
        var se = new SurveyEmbed("<YOUR-SURVEY-ID>", "https://forms.office.com/", "https://mfpembedcdnweu.azureedge.net/mfpembedcontweu/");
        var context = {
            "contactId": contactId,
        };
        se.renderInline(parentElementId, context);
    }

Key things here are 2 parameters:

  • parentElementId
  • context

parentElementId parameter is just a string value that represents an id of the div that will be used as survey container.

context parameter is used for sending additional data to the survey response activity that is created once you submit the survey.

Let's make some small changes to the code to make it work in our case. We need to add container DIV for the survey and get the contact id from the form context.




    
    



    
    
        function renderSurvey(contactId) {
            var se = new SurveyEmbed("<YOUR-SURVEY-ID>", "https://forms.office.com/", "https://mfpembedcdnweu.azureedge.net/mfpembedcontweu/");
            var context = {
                "contactId": contactId
            };
            se.renderInline("survey-container", context);
        }
<div></div>
        var contactId = parent.Xrm.Page.data.entity.getId().replace("}","").replace("{","");
        
        renderSurvey(contactId);
    


Now when we did some modifications we need to create new HTML web resource in Dynamics. It will be called fic_Embed.html and content will be just the same as the one in the code box above.

After that add a new tab to the contact form and inside it add a section with a web resource (in this case fic_Embed.html).

You should see something like this when you save and publish the form and open a Survey tab.

Congratulations, you have successfully added a survey to your Dynamics form.

Now we need to see what is going on with data created in the background. Let's test the survey with options Dynamics 365 and rate it as 5 stars. After we submit the answers some records will be created in the background.

The first record that is created is Survey response record, which is the activity entity by the way. It contains a few fields that are important in our case.

The Subject field is a field that is inherited from activity entity and it's blank when you submit the survey which is not great in our case because we want to show the activity in the Timeline.

Context Data field is a field that contains JSON object with one core node called EmbedContextParameters that contains all the custom parameters (only one contactId in our case) that we posted in JS code.

Every Survey response record has his child entities called Survey question responses. Those records hold the values of the submitted answers. Answers are stored in the Response field in plain text format.

Now when we know how the data is stored it's time to make a Flow that will transform the data in the way we want.

Let's make a blank Flow to start.

Trigger that will be used is Common Data Service one that is triggered when the Survery response record is created.

The first action will be used to retrieve all Survey question responses related to the record that triggered the Flow.

The only parameter we need to set here is a filter query that will filter our all related question responses. Survey response GUID is hidden in Activity parameter from the trigger. Question responses are always returned in the order that is the same as question numbers sorted ascending.

Next, we need to parse the JSON that is holding EmbedContextParameters from the Context Data field of Survey response entity.

Schema that is generated by payload looks like:

{
    "type": "object",
    "properties": {
        "EmbedContextParameters": {
            "type": "object",
            "properties": {
                "contactId": {
                    "type": "string"
                }
            }
        }
    }
}

Finally in the last step of the Flow we will update the Survey response entity.

As record ID we will use Activity field from the trigger. Regarding field has 2 parts. Regarding needs to be set to the contactId value that we got from the JSON in the previous part and the Regarding Type needs to be set to contacts.

The subject is the part that will be shown in the Timeline so we need to put something human readable here. Let's concatenate the answers of the questions with "-" sign in between. We know that in returned Survey question responses dataset answer of the first question will be returned as the first item in the array and the answer of the second one will be returned as the second item in the array. Knowing that it's easy to make a concatenation.

First body(...) part from Subject field in the picture must be equal to:

body('Get_Question_Responses')?['value'][0]['msfp_response']

Second body(...) part from the Subject field in the picture must be equal to:

body('Get_Question_Responses')?['value'][1]['msfp_response']

After we set those parameters in the last action and started the Flow everything is ready for the final test.

Let's submit new answers to the same contact as before.

After we submit the answers we should wait for a few seconds for Flow execution and then refresh the Timeline on the contact entity.

Well done if you see the submitted answers on the Timeline!

Conclusion

It's quite easy and intuitive to work with survey answers once you understand the data model in behind, but I see there so much to be done. As I said at the beginning I see big potential in this for dialog scenarios in the future, but first, they need to change the authentication method to the same domain as Dynamics so we can use it anywhere on the form.

I'm really looking forward to this feature and I think that big things will come really soon because feedback in the community regarding the feature is just huge.