Category: Dynamics 365 CE

Install Level Up for Dynamics 365 on Microsoft Edge

Install Level Up for Dynamics 365 on Microsoft Edge

One of the tools I use on a daily basis (as a Power Platform consultant) is Natraj Yegnaraman’s Level Up for Dynamics 365. It’s an extremely usefull tool that helpt me developing, analysing issues, navigate through the application and many more.

Unfortunately, this tool is made for Google Chrome only, since it’s a Chrome extension. And since I have multiple orgnisations and tenants open on a regular basis, I also use other browsers than only Google Chrome. Lucky, from now on you can use Chrome extensions in the new Microsoft Edge!

Get Edge to install Chrome extensions

  1. Open Microsoft Edge
  2. Chlick on the Settings (three-dotted) button on the top right corner and select Extensions
  1. Turn on Allow extensions from other stores and click Allow afterwards

Install Level Up for Dynamics 365

  1. In Edge, open the Chrome Web Store and go to the extensions page (or just use this link 🙂 )
  2. Now just click Add to Chrome and you’re all set to go!

Enjoy!

Using Power Automate (Flow) to merge contacts

Using Power Automate (Flow) to merge contacts

When using Power Automate, there is no default method in the Common Data Service connector to merge accounts, contacts, leads or incidents. As you can see, there is only the ability to create, update or delete records.

That’s a bummer, cause sometimes you want to merge twee records. Luckily it’s possible! You just have to know how.

In the example I’ve got to merge two contacts. I assume you already know how to get the proper contact records, so I won’t go over that.

Since there is no method in the connector, we’ll have to build it ourselves. We’ll use the HTTP method on the HTTP connector.

Start the setup

To setup the HTTP call, let’s start with the basics. Give your action a proper name! Please don’t think lightly about naming actions, since it’s so important to do that right away. It organizes the whole flow so if anyone needs to change it afterwards, they still understand what it’s doing. I named my step ‘Merge Contacts’. Makes sense, right? 🙂

The most properties in the HTTP call are easy and fixed. Some of them need some more attention. Let’s first do the easy properties.

  • Method is always POST
  • URI is your CDS / CRM url with the addidion ‘/api/data/v9.1/Merge
  • For the Headers, we need two additional headers
    Accept | application/json
    Content-Type | application/json; charset=utf-8
  • You may leave the Queries empty
  • For the body, please start with this code
{
  "PerformParentingChecks": false,
  "Target": {
    "@@odata.type": "Microsoft.Dynamics.CRM.contact",
    "contactid": "00000000-0000-0000-0000-000000000000"
  },
  "Subordinate": {
    "@@odata.type": "Microsoft.Dynamics.CRM.contact",
    "contactid": "00000000-0000-0000-0000-000000000000"
  },
  "UpdateContent": {
    "@@odata.type": "Microsoft.Dynamics.CRM.contact",
    "contactid": "00000000-0000-0000-0000-000000000000"
  }
}

Now let’s have a look at the body. There are two things you need to change at least. First on line 5, we have the ID of the contact that will be the target. We’ll merge both contacts to this one. Replace the 00000000-0000-0000-0000-000000000000 with the contact id. Look in your previous steps for Contact field with a description containing the Unique Identifier. The double quotes should still be around the Contact field. Second, you need to do the same with with your other Contact, but on line 9.

The only thing that is still to be done is the authentication. Since this is not a predefined connector, you’ll have to deal with the authentication yourself. Authenticating to CDS always works based upon Active Directory oAuth. The tenant is your onmicrosoft.com domein (i.e. consoto.onmicrosoft.com), the Audience your CDS ul and the Credential Type can be set to Secret. The only two things that are left are the Client ID and Secret. You need to setup server-2-server authentication to get these two. If you want to know how? Check my other blog about authenticating with server-2-server authentication.

That’s it! You’re all set and can automate the merge of contact records in CDS.

Customizations.xml Advanced Hacks

Customizations.xml Advanced Hacks

For those who attended my session about customizations.xml advances hacks, here is everything I promessed you during the session.

The presentation

Here’s the PowerPoint with the relevant information.

Enable / Disable the Jumpbar on subgrids

First example was to enable or disable the jumpbar on subgrids. In order to do so, you need to add or set the <EnableJumpBar> property in the parameters of the subgrid as shown below.

<cell showlabel="false" locklevel="0" id="{a64dbfbd-4d31-4b01-99a8-d6019536c1a5}" rowspan="1" colspan="1">
  <labels>
    <label description="New SG control 1573914400892" languagecode="1033" />
  </labels>
  <control id="lbs_contacts" classid="{E7A81278-8635-4D9E-8D4D-59480B391C5B}" indicationOfSubgrid="true">
    <parameters>
      <TargetEntityType>contact</TargetEntityType>
      <ViewId>{00000000-0000-0000-00AA-000010001004}</ViewId>
      <ViewIds>{00000000-0000-0000-00AA-000010001003},{00000000-0000-0000-00AA-000010001004}</ViewIds>
      <EnableViewPicker>false</EnableViewPicker>
      <RelationshipName>lbs_Event_Contact_Contact</RelationshipName>
      <EnableJumpBar>false</EnableJumpBar>
    </parameters>
  </control>
</cell>

Hide columns on your view

To hide columns on your view, you can set the ‘ishidden’ attribute on the column of the view as shown below.

One of the attendees on the session in Brussels also marked the ‘disableSorting’ attribute that makes sure users cannot sort the view on that column.

<layoutxml>
  <grid name="opportunityproducts" jump="" select="1" icon="1" preview="1">
    <row name="opportunityproduct" id="opportunityproductid">
      <cell name="productid" width="200" />
      <cell name="productdescription" width="200" />
      <cell name="priceperunit" width="100" />
      <cell name="quantity" width="75" />
      <cell name="extendedamount" width="100" />
      <cell name="opportunityproductname" ishidden="1" imageproviderfunctionname="Sales.ProductTypeImage.getProductTypeImageUrl" imageproviderwebresource="$webresource:Sales/ClientCommon/Sales_ClientCommon.js" />
      <cell name="isproductoverridden" />
      <cell name="producttypecode" ishidden="1" disableSorting="1" />
      <cell name="baseamount" width="100" />
    </row>
  </grid>
</layoutxml>

Embed PowerBI Report in a Model Driven form

Microsoft has documented this feature well and you’re able to see all information on this page. Down here is the code that needs to be added to the section under the </labels> tag. To filter on the current record, please add the highlighted line. Also don’t forget to set the height of the section by adding rowspan=”10″ to the <cell> tag.

<control id="unfilteredreport" classid="{8C54228C-1B25-4909-A12A-F2B968BB0D62}">
  <parameters>
    <PowerBIGroupId>00000000-0000-0000-0000-000000000000</PowerBIGroupId>
    <PowerBIReportId>91649484-1601-4345-8c12-4dfea5d69399</PowerBIReportId>
    <TileUrl>https://app.powerbi.com/reportEmbed?reportId=91649484-1601-4345-8c12-4dfea5d69399</TileUrl>
    <PowerBIFilter>{"Filter": "[{\"$schema\":\"basic\",\"target\":{\"table\":\"Account\",\"column\":\"accountid\"},\"operator\":\"Eq\",\"values\":[$a],\"filterType\":1}]", "Alias": {"$a": "accountid"}}</PowerBIFilter>
  </parameters>
</control>

Creating custom dialogs

In the presentation I told you about custom dialogs in CRM. These are perfectly to build and it’s all explained very well by Bob Guidinger. You can find everything you need to know on these two posts: https://bguidinger.com/blog/category/dialog-boxes

Force users to use the Unified Interface

Force users to use the Unified Interface

You can’t have missed it. All Dynamics applications that are based on the PowerPlatform will be using the same interface: the Unified Interface. Microsoft has announced deprecation of the the ‘old’ web client (see this article for more information), so there’s no way back. On October 1, 2020, the legacy web client will no longer be available.

Have you already migrated all your users to the Unified Interface? GOOD! I guess you probably face the same problem as I do than. When users log on, they are still routed to the legacy web client! They keep on working in this new client instead of the new… As of October 2019 we’re able to force users to use the Unified Interface (whoop whoop!).

How to activate this force?

First, login to your Dynamics 365 CE environment and open the PowerPlatform Admin Center. Now go to the environments tab and select the environment where you want to activate the force. Go to Settings > Behavior > Interface settings and then turn on Use Unified Interface only.

Frequently Asked Questions about this change

Is there any downtime while applying this change?

No, this change applies immediately, upon reloading the page. If it doesn’t, clear cache and retry.

I want to use Unified Interface for all the apps, but still want Dynamics 365 – custom to open in the legacy web client. Is that possible?

You can achieve this by setting all apps to be Unified Interface apps. Note that this won’t change the home page experience to Unified Interface. Unified Interface Only mode is a prerequisite to get the new home page experience.

What app will be opened when the force is activated?

When the user has access to only one app, they will be routed to that app without any problems. When they have access to multiple apps, they will be routed to https://home.dynamics.com and will have to choose on of the apps.

Please give us the Outlook Add-In in PowerApps

Please give us the Outlook Add-In in PowerApps

UPDATE: Ok, in the meantime a couple of people showed me the feature. Apparently it’s available after all! I was looking for server-side sync as I always thought the Outlook Add-In only works with server-side sync. However, it turns out the Outlook Add-In works without server-side sync and is available in CDS. Here’s the link: https://powerapps.microsoft.com/en-us/blog/introducing-the-powerapp-that-brings-common-data-service-into-outlook/

As a Dynamics 365 Solution Architect, I’ve done a ton of xRM projects. Using the good-old Dynamics CRM platform as a app-builder instead of using the Sales and Customer Service functionality in there. So you probably can’t imagine my enthusiasm when Microsoft brought us the PowerPlatform. It’s basically what I needed: a flexible platform to build business applications without Sales or Customer Service functionality. Thank you Microsoft! 🙂

Now that I’ve done the first couple of projects on the new PowerPlatform I’m totally happy. However, there is one feature from the Dynamics 365 platform that I really miss in almost every PowerApp: Server-Side Synchronization with the Outlook Add-In.

The ability to track e-mail is an ability that is needed in a lot of business scenario’s. Not only in Sales and Customer Service scenario’s. Currently it’s only available with the Sales and Customer Service apps. I encourage Microsoft to make it available in all PowerApp scenario’s. Please, Microsoft, give us the Outlook Add-In in PowerApps!

The loophole for now

So if you ran into the same issue and you’re looking for a solution to use the Outlook Add-In in a PowerApp, here’s what I do. For those users who need an Outlook Add-In, I provide them with an additional Team Member license on top of the PowerApp license. Please make sure to create a Dynamics 365 environment instead of a regular CDS environment. The regular CDS environment won’t contain the proper entities to use Server-Side Synchronization.

Dynamics 365 and PowerPlatform API Limits explianed

Dynamics 365 and PowerPlatform API Limits explianed

Together with a lot of other Dynamics 365 / Power Platform professionals, I was very surprised with the announcement of Microsoft about API limits. Now that the dust has settled and the documentation has cleared some first questions, we’re able to review the decision.

My first thought about the API limits were: there goes one of our unique selling points against Salesforce. But the more I think of it and the more I talk to Microsoft product managers about it, it starts to make sense. Both from a technical point of view and strategy wise.

What is an API call?

First, let’s dive a little bit into the changes made lately. You can’t have missed the huge strategy change within the Dynamics 365 (CE) landscape lately. It simply comes down to this. The PowerPlatform – as a platform to create business applications on – becomes the base of it all. The Sales and Customer Service functionality (formally known as Dynamics CRM) are applications developed by Microsoft on top of that PowerPlatform.

At the heart of the PowerPlatform is the Common Data Service. A database where both your business data and your application business logic (metadata) is stored. The amount of usage of the Common Data Service defines the resources needed. Every time that a user or an application requests data from the Common Data Service or pushes data towards it counts as an API call.

Do I need to worry about the limits?

No, I don’t think so. If you assign an appropriate license to the user. The API limits that come with the licenses are based on normal usage. Are you a heavy user? I still don’t think that should be an issue.

So I don’t need to do anything?

Well, with this change it’s more imported then ever to really think about your solution design. If you create forms that have an enormous amount of subgrids on it, that’ll consume more API calls. If you don’t need it as immediate information, please put it one click away. Also think about your custom coding! Inefficient JavaScript or plugins can lead to a significant increase of API calls.

Why tell me why

Let’s face it: all of us had experienced performance issues with environments in the past. When a ticket is logged with Support, it often has to do with another customer having extreme data loads, pushing the underlying servers to the max. When this happens, it comes down to performance degradations of other environments running on the same server.

Microsoft has been searching for a way to manage these problems, but the only way they can manage is if they know what’s coming. At this moment, there is no reason why a customer would tell Microsoft it’s going to do a large data load or anything else that takes a lot of resources.

By limiting the API usage and letting customers buy API call packages, Microsoft pushes consultants and developers to think about the usage of resources and providing Microsoft the information it needs to allocate enough resources.

So everything is fine?

From a technical point of view: yes. From a commercial point of view: absolutely not!

Not having API limits was one of the unique selling points against Salesforce. For companies using a lot of data processing or having a lot of integrations, the choice between Microsoft and Salesforce is now less self-evident. Next, the price for extra API calls seems pretty high to me.

At this point, the limits are user based. This means individual users getting punished for using the application. That doesn’t make sense. The reason for Microsoft is environment-wide and should not be applicable to customers, but to the whole environment.

Please, Microsoft, make the API limits an environmental limit and not a user-based limit!

Creating a custom Status for your (custom) entity

Creating a custom Status for your (custom) entity

It’s been always a mystery to me why we’re not able to change the status field on an entity. We just get to change the status reason field, but sometimes you just want some more. Microsoft knows it, cause they use multiple status fields on for instance the Lead and Opportunity entity.

Let face it: most of the time it’s just fine to have Activate and Inactive as statuses on your entity. (Now that we’re talking about statuses… Isn’t it just weird that Active has the value 0 and Inactive the value 1??!) But there are those situations that you just need more. For instance one of my customers log their medical consults in an entity. In this case it would have been great to have Active, Processed and Invoiced as statuses. And you know what: it’s possible!

Now before you get too excited about this I need to temper your enthusiasm a bit. Although it can be done, it’s unsupported customization. When you read my solution and you read this article, you’ll understand why it’s unsupported. Since it’s unsupported, I would strongly advice you to do this only for custom entities and not for oob entites. So far for the disclaimer 🙂

In order to add or change the statuses you need to change the customization xml file. Now let’s go through the steps. (I expect you to have some experience with customizing Dynamics 365 CE. If not, please contact your Microsoft partner to execute these steps.)

Create the solution and get the right file

Create a temporary solution with just what you need. In this case, just add the status and status reason fields from the entity you wish to change. Although you just want to change the status field, you’ll also need the status reason field. Later on it’ll come clear why that is needed.
Export the solution and open the zip file. Now get one file out – the customization.xml file – and store it somewhere to edit.

Edit the customization xml

Now comes the editing of the file. Please be careful here, cause you might break something here.
In the file, locate this part

<states>
  <state value="0" defaultstatus="1" invariantname="Active">
    <labels>
      <label description="Active" languagecode="1033" />
    </labels>
  </state>
  <state value="1" defaultstatus="2" invariantname="Inactive">
    <labels>
      <label description="Inactive" languagecode="1033" />
    </labels>
  </state>              
</states>

As you can see, both default statuses (Active and Inactive) are there. Notice the defaultstatus tag that is in there. This is important and indicates the default status reason for that status. Since we don’t have a status reason for it yet, we will just fill in a random number now that we’ll use later to create the status reason with.

To create the new status just copy everything between a <state> and </state> tag and change the value, defaultstatus, invariantname and desciption. It should look like this. In this example I use Invoiced with vaue 10000. I would always use a high number as you never know what Microsoft comes up with in the future.

<states>
  <state value="0" defaultstatus="1" invariantname="Active">
    <labels>
      <label description="Active" languagecode="1033" />
    </labels>
  </state>
  <state value="1" defaultstatus="2" invariantname="Inactive">
    <labels>
      <label description="Inactive" languagecode="1033" />
    </labels>
  </state>
  <state value="10000" defaultstatus="20000" invariantname="Invoiced">
    <labels>
      <label description="Invoiced" languagecode="1033" />
    </labels>
  </state>                  
</states>

Now we need to do the same for the status reason field. Please keep in mind the value for the status reason should be equal to the defaultstatus value that we’ve used before. The same goes for the state.

<statuses>
  <status value="1" state="0">
    <labels>
      <label description="Active" languagecode="1033" />
    </labels>
  </status>
  <status value="2" state="1">
    <labels>
      <label description="Inactive" languagecode="1033" />
    </labels>
  </status>                    
  <status value="20000" state="10000">
    <labels>
      <label description="Invoiced" languagecode="1033" />
    </labels>                    
  </status>
</statuses>

Import the file and you’re done! 🙂

Now that you’ve changed the cusomization xml file you should put the customization xml file back into the solution zip. Notice that it overwrites the existing customization xml file. Import the solution zip back into your environment and you should have the new status.

Things to take into consideration

Again, this customization is not supported. Always be careful with these unsupported customization and question yourself if you can’t do it any other way.

Since it’s unsupported, the user interface doesn’t take your new status into account. There is no out of the box option to set a record to your new status. You can use workflow or you’ll have to create a button on the command bar to set your status.

Last but not least: as for as I could see, when a record is in the new status, its forms are always in read-only state. The Active status is the only status where you can edit the data on the form.

Nested groups not supported in Dynamics 365 CE

Nested groups not supported in Dynamics 365 CE

So at my current CE project, we want to work with guest user access in CE. This company uses an external company to process incoming e-mail and phone calls. They would like the users from the external company to directly login to their CE instance and do their jobs. This can be done perfectly by the new guest user feature in CE.

Now from a maintenance perspective in Azure Active Directory, you’d like these specific guest users to be in a separate group, so you have them grouped together and can maintain them all together. That would mean you have two security groups with users that need to access the same CE instance. Unfortunately, you can only have one security group setup for accessing one CE instance… :-(.

But wait, what about nested security groups! I created a third security group and made two other security groups member of the third. But when I added the third security group to the CE instance, nobody could login anymore… There was the gap: nested security groups are simply not supported. So we ended up with one security group that had all users in it. Not particularly Azure Active Directory best practice, but it worked 🙂

Also want support for multiple or nested security groups? Good! Vote for my idea here.

Activation Failed status on Data Export Profile

Activation Failed status on Data Export Profile

I’ve setup the Dynamics 365 Data Export Service numerous of times and I’ve made a lot of companies happy with this service. Having your Dynamics 365 CE data in a separate database has advantages for reporting, but also for data quality checks.

In my current project, we’ve done a data migration from a previous custom application to Dynamics 365 CE. This customer had a huge amount of data and we ended up with a Dynamics 365 CE database of 150 GB of data. After the migration we wanted to do some checks if all data had been migrated correctly. We used the Data Export Service to make that possible.

When we created the Data Export Profile we simply checked the ‘Select all’ option, since we wanted to do quality checks on ‘all’ data in the database.

Unfortunately, we got an error immediately when we finished the wizard!

After some digging, we found the issue. There are some entities in Dynamics 365 CE that are available for selection in the entity list (since they are track change enabled) but seem to break the Data Export Profile. The entities I found so far are:

  • mobileofflineprofile
  • mobileofflineprofileitem
  • mobileofflineprofileitemassociation
  • offlinecommanddefinition

Simply uncheck these entities and you are good to go!