Get Data sent to server on Save using Dynamics 365 CRM JavaScript | GetDataXML function

D365 Demystified

Now, in case you are working on forms in Dynamics 365 CRM, and you want to know what all data is changed – There are 2 ways to get this

Scenario

Let’s look at the below scenario where this is useful –

  1. You have a record which you are about to Edit. This is how it looks as of now.
  2. Now, I have an OnSave event on which I’m calling a function to capture what all is being saved.
  3. Now, below is what I want to change and then click Save to save the changes.
  4. And then click Save. Now, I want to capture all this data upon Saving to know and further process what has been changed. Let’s see how we can achieve this using Dynamics 365 CRM JavaScript

getDataXml() method

Here’s how you will see the data to be changed

  1. Below, you see that I’m using to get…

View original post 329 more words

Advertisement

Improve fetch xml performance by using latematerialize option.

If you have been working on dynamics projects, I bet fetch xml is your best friend as it’s really an easiest way to query and execute in order to get required results. Along with that, constructing it in advanced find is super easy too.

Don’t forget about amazing XRM toolboxes which helps you creating even complex fetch xml queries.

It all sounds fun and easy till your fetch XML becomes really heavy with so many joins or you have a requirement where you need to make many joins.

A Quick tip!

You can have a maximum of 10 joins in fetch xml for dynamics CE.

You will notice that retrieval from dynamics is getting slower and slower as fetch xml becomes complicated. I have faced something similar multiple times. What I did?

well, there are multiple options one of which I want to cover today as using this option, there are no extra efforts.

latematerialize to the rescue!

All you got to do is add latematerialize=”true” in fetch xml properties like below and test is to see the magic.

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" latematerialize="true">
  <entity name="account">
    <attribute name="emailaddress1" />
    <attribute name="statecode" />
    <attribute name="statuscode" />
    <attribute name="ownerid" />
    <attribute name="accountnumber" />
    <link-entity name="contact" from="contactid" to="primarycontactid">
      <attribute name="birthdate" />
      <attribute name="createdon" />
      <attribute name="contactid" />
      <attribute name="parentcustomerid" />
    </link-entity>
  </entity>
</fetch>

There are many internal technicalities as to how it works but to summarize, It breaks the data into multiple smaller segments which makes the retrieval of data faster unlike normal fetch xml which tries to query every at once.

if you are looking for official documentation on the same, please go here: Improve FetchXML request performance – Power Apps | Microsoft Docs

No “Change Tracking” option available under entity definition?

No change tracking available under entity definition.

To be able to add an entity to data export service, you would need to make sure the change tracking option is enabled on the entity definition.

we generally go to Settings – > solution or customize the system -> look for the entity and under “Data services” option, you should see the change tracking option. However it’s not the case anymore.


The option has disappeared from classic UI entity definition.

So where is this setting now? Well, you will find it in https://make.powerapps.com portal now. In order to see it, go to powerapps portal or click on above url.


1. Make sure you in the right environment from top right corner.
2. Click on solutions from the left menu:

3. Select the solution in which entity is there or default solution.
4. Navigate to the tables and click on the desired table and click on edit.


5. Again click on “edit table properties”

6. Expand advanced option section and select the “Track Changes” Option:

And that it! you should be good to go after publishing.

Get Contacts/Customers Used In A Customer Journey In Dynamics 365 Marketing

This is going to be a very short blog as I am going to just reference my previous blogs to achieve a solution for this.

I have talked about Customer Journey entity in dynamics in a recent post here:  The ‘Mysterious’ Customer Journey Entity In Dynamics 365 Marketing.

By now, we know that it’s not easy or straight forward to get any details from a customer journey from the back-end.

segment1

In a customer journey, customers are not directly added but rather through a “Marketing Segment”. Now we have seen in the blog above on how to get segment details used in the journey. Once we have the segment Id, the next step is to fetch the customers from the segment and for that I have another blog explaining it: Dynamics 365 For Marketing – Retrieve Contacts From A Segment

By doing the above mentioned, you should be able to get all customer that are part of a journey.

I hope this helps.
Cheers!

 

The ‘Mysterious’ Customer Journey Entity In Dynamics 365 Marketing

In today’s blog I am going to be talking about ‘Customer Journey’ entity in dynamics 365 for marketing app or to be specific the ‘Customer Journey Designer’ which looks like below:

customerjourney1

 

I call it ‘Mysterious’ because whatever happens in the journey ‘stays’ in the customer journey. i.e there is no way or its difficult to get the segment/contents being used in it. I am talking about Marketing Email, Marketing Page, Marketing Form etc. The question you might want to ask is why would I need that information? well, because of may be below:

  1. You might have some validations on the content you can use in the customer journey
  2. You might want to retrieve the data for reporting purpose

If you look into the relationships from customer journey to these entities, you wont find anything hence it gets difficult to retrieve these records or perform operations. In short Dynamics 365 Marketing works a little differently then our typical dynamics 365.

Whatever happens inside a customer journey designer sits in a field on this entity named as “msdyncrm_workflowdefintion“. It stores information about content added in this the journey in JSON format. 

customerjourney2

This is how it looks:
customerjourney3

 

Let’s understand what this JSON means:

  1. Each content is stored in a node called “ActivityTypeId“.
  2. The Id of the content is stored in property “Itemid“.
  3. To identify the type of content such as Marketing page form etc. refer to below table because it uses different names to each type of content:

Dynamics Entity Name Internal Name In Customer Journey
Marketing Page LandingPage
Marketing Form MarketingForm
SurveySurvey
Marketing EmailEmail
Marketing Event Event
Marketing SegmentSegment

If you debug and parse this field data into JSON, looks like something below:

customerjourney4

So when you retrieve/query this field, you have to loop through these JSON nodes and do validation using the Guids of these records like in the below example of Javascript:

 var workflowDefintion= formContext.getAttribute("msdyncrm_workflowdefinition").getValue();
 var workflowDefintionData = JSON.parse(workflowDefintion); //Parse it

                    var nodeLength = workflowDefintionData.length;
                    for (var i = 0; i < workflowDefintionData.length; i++) {
                        var node = workflowDefintionData[i];                        
                        /* Check if node is a Marketing page*/                       
                        if (node.ActivityTypeId === "LandingPage" && (i + 1) === nodeLength) {

// Perform Operations here
}

Same way you can do in the code if needed.

I hope this help!

Cheers!

Import Member/Contacts To A Marketing Segment

A segment in 365 for marketing app is an essential feature which lets you create a list of related contacts based on some criteria( similar to advanced find). Later it is used to target customers in a customer journey.

While you can define a criteria/search for contacts and add them in a Dynamic segment, you don’t have this facility in a “Static” Segment because contacts are manually added on a per-contact basis. hence, there should be ability to import these contacts in to a static segment. 

Now, there is no out of the box way I could find by which we can bulk update contacts into a segment, however after doing a bit digging, I found a working custom solution. 

Solution

If you look into segment entity, you will find a mysterious field named “msdyncrm_segmentmemberids” as below:

segment1

This field basically consists of the ids of the contacts in a JSON format prefixed with “crm”:

segment2

Hence, whatever contacts you manually select on the segment comes and sit in this field. So we just need to update this field with ids of the contact we want to include in this segment.

You can update this field either by WebApi or a Plugin. Its upto you how you want to design your solution. In my case I have placed button on the segment form which opens a web resource providing a flexibility to upload an excel/csv file containing these ids of the contacts which you can easily read, prepare the format of the guids(prefix with “crm”) and update using a simple web api request.

 var entity = {};
            var stringIfy = JSON.stringify(Prepared_ContactsArray);
            var entity = {};
            entity.msdyncrm_segmentmemberids = stringIfy;

            var req = new XMLHttpRequest();
            req.open("PATCH", GetGlobalContext().getClientUrl() + "/api/data/v9.1/msdyncrm_segments(" + segmentId + ")", true);
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.onreadystatechange = function () {
                if (this.readyState === 4) {
                    req.onreadystatechange = null;
                    Xrm.Utility.closeProgressIndicator();
                    if (this.status === 204) {
                        //Success - No Return Data - Do Something
                       
                    } else {
                        //Xrm.Utility.alertDialog(this.statusText);
                    
                    }
                }
            };
            req.send(JSON.stringify(entity));
        }

I hope this helps!

Cheers!

Enable Custom Entities For Marketing Segment Dynamic Query

A segment in 365 for marketing app is an essential feature which lets you create a list of related contacts based on some criteria( similar to advanced find). Later it is used to target customers in a customer journey.

So when you create a new segment you have an option to create it as static or dynamic. A dynamics segment is what lets you add a query to filter contacts.

picture depicts a dynamic segment query designer

However, there is one thing that will bother you which is, it will not let you add a related custom entity to form a query ( click on add group and select union as relationship)

Solution

There is a settings available in Marketing app which will let you enable this feature for any entity in your system. To check this, go to Marketing App — > Settings Section:


Under Marketing Settings, click on advanced settings.
Now click on Customer Insights Sync under marketing setting section which will give you the list of entities on the right side with check boxes.

Enable for the entities which you need and click on publish from the header.

You might see the box is grayed out and you will not have option to enable. To enable the box you need to enable the change tracking on that entity. to do that you have to go to that entity definition and enable change tracking check box. https://docs.microsoft.com/en-us/power-platform/admin/enable-change-tracking-control-data-synchronization

Once published give it some half an hour.

Navigate to your query now and you will be able to add related entities to your query just like advanced find.

I hope this helps!

Plugin on Retrieve Multiple in CRM.

Filtering records using javascript in subgrid or a view is unsupported and doesnt work hence here is how you can/should filter subgrid records using a plugin.

Nishant Rana's Weblog

Recently we had a requirement to filter sub grid on one of the forms. We thought of using Plugin on Retrieve Multiple for this.

Here we were showing Opportunity Sub Grid on Account form.

So we created a view for Opportunity that will be used as Sub Grid. Used it as Related Record Sub Grid so that we can have the GUID of the Account record being passed to the plugin.

The problem we faced à Sorting and Paging stopped working for the Sub Grid.

http://crmtipoftheday.com/2015/10/05/limitations-of-retrieve-plugins/v

Hope it helps..

View original post

Quick Fix : Mandatory Field Error Shows Schema Name Instead Of Display Name

Quick blog on how to fix the error you get when you save a record which has some required fields on the header of the form and CRM shows the schema name instead of display name like below:

1.png

it shows the error which includes specific field logical name instead of display name which might be confusing for user and doesn’t look very much user friendly. In my case its still very much understandable but sometimes people change name on the form and in that case it will be worse situation.

FIX :

All you have to do is put the same field on the form which is there on the header and hide it on the form. Open the form editor > select the section > look for the field and add it. Go to field properties and hide it by unchecking the visible by default box:

1

Save and publish all your changes and now try to save the record:

1.png

I hope this help!

Handle Boolean/Two Option Fields In Scribe Data Migration/Bulk Update

I know many CRM developer get into Data migration or bulk update operation from CRM system to other external/CRM system.

I have gathered few useful tips while dealing with boolean fields as in how to check the value , reverse the value , use nested if with OR & AND conditions etc. I have categorised them into below and provided explanation & solution.

  1. Check Values from Source & Set New Value 

    To check value of a boolean field from source do this and set other value:

    IF(S1=1, 0 , 1)

    (Here i am checking if S1 field value is “1” which is “TRUE” then set the new value to “0” which is “FALSE” otherwise the default will be to “1”.)

  2. Check Combination of boolean fields and Set New Value

    To check the combination of values i.e If a=1, b=0 then set some new value, Do this:

    IF(AND(S1=1, S2=1), 0 , IF(AND(S1=0, S2=0),1 ))

    (here i am checking if S1=1 AND S2=1 then outcome should be “0”.
    please note: you can use “OR” operator as well as per your requirement.)

  3. Check If the value is Null or Any error in retrieving the value and set default value

    You might have to handle null values in the package, to do this:

    IF(ISERROR(S1),TRUE(), FALSE())

    (here I am checking if S1 is null or any error then i am setting the value to TRUE otherwise FALSE.)

    you can also combine this with checking other values to such as if S1 =1 then 1 , S2=0 then 0 & if S2=Null then TRUE().

    IF(ISERROR(S1),TRUE(),IF(OR(S1 =1 ), 0,IF(OR(S1=0),1)))



    I hope this helps! I will try post help blog on other types of fields.
    cheers!