Tip #1319: Double the single quotes

tl;dr

If you have email addresses coming from somewhere and you’re using them in Power Automate to filter and find the records, make sure to double the quotes.

Full story

One of the observations made by our lifetime tipster Jerry Weinstock was that citizens tend to create automations that follow happy path. I have to say this turned out to be valid for yours truly as well.

Am I becoming a citizen?! o__O

The Enabler

I was processing some records that came from a spreadsheet and needed to look up CDS records by email. That part of my flow looked something like this:

Happy – 3000, unhappy – 2. Diving in.

That explains it. According to RFC5322, the recipient part may use any of these ASCII characters:

  • Uppercase and lowercase English letters (a–z, A–Z)
  • Digits 0 to 9
  • Characters ! # $ % & ‘ * + – / = ? ^ _ ` { | } ~
  • Character . (dot, period, full stop) provided that it is not the first or last character, and provided also that it does not appear two or more times consecutively (e.g. John..Doe@example.com)

All of these characters are probably fine except the quote that breaks the fragile syntax of JSON land. So the expression catering for unhappy path has become:

And everyone is happy now, including the unhappy path with 6 quotes in a row.

Photo by Dominika Gregušová from Pexels

Tip #1318: Why don’t I see the “associated records” link in subgrids?

In unified interface, when you click on the more option button, you will sometimes see the the option to see the related records in the subgrid.

This is handy, especially when you want to see all of the view options, like filters.

But sometimes you might see the “see all records” option instead. This is not very handy, as it shows you all of the records in the related entity, and you don’t have all of the view options.

The reason why you don’t see the “see associated records” option in your subgrid is because you do not have the entity in the subgrid displayed on the navigation area of the form. Add the entity in the subgrid to the form navigation menu/related records are of the form on which the subgrid lives, and you can start viewing your associated records.

Tip #1317: Make lead qualification better with Power Automate

You work on a lead in Dynamics 365–you have several conversations and enter some notes.

After you qualify the lead, the activities show up on the account or contact record that was created in the qualification process, but the notes are left behind on the lead.

Power Automate to the rescue!

Create a Flow that runs on create of a contact (or account if you are qualifying leads to accounts).

Action 1: Get lead record (to get all details)

Action 2: Condition: If originating lead equals null, terminate

Action 3: List records — get notes where objectID equals contact originating lead.

Action 4: condition: length(outputs(‘List_records’)?[‘body/value’]) is greater than 0 (does #3 return any notes)?

If yes, Apply to each and update the note, setting the regarding to the contact.

End result? Your lead notes are now linked to the newly created contact.

Cover photo by Min An from Pexels

Tip #1316: Do form embedded charts work in unified interface?

I heard that you can’t put charts on form in Dynamics 365 unified interface. Is that correct?

Tip Jar

We’ve received this question from several readers, so I decided to check it out.

I did this in Dynamics 365 Online v 9.1. I don’t know if this works in on premise 9.0.

  1. Add a subgrid to your form
  2. View subgrid properties
  3. In the chart options area, check the box for show chart only

VOILA! CHART!

This tip has been Chart Guy Verified™. It doesn’t show the chart if you don’t check the show chart only box. sorry no chart/view combo subgrids.

Cover photo by unsplash-logoDan Meyers

Tip #1315: How to remove Field Service from Dynamics 365

Disclaimer for Ben Vollmer: We love field service. If it was food, we would eat it at every meal.

That out of the way, sometimes you find yourself with solutions in your environment that you don’t need. Maybe you set up a trial of Dynamics 365 and you accidentally chose the “I want it all” option and wound up with a bunch of managed solutions in your environment. This can be bad, as any solution you develop in this environment will have a dependency on these solutions, requiring you to install them before you can move your solution.

If you find yourself in this situation, you will want to remove these solutions from your environment. But that can be challenging, as many of these apps install multiple solutions in your environment.

In this video tip, I show you how to determine the order in which these solutions should be removed and then successfully uninstall field service from a Dynamics 365 environment.

I removed Field Service and lived to tell the tale

I did see the Skyline Consulting blog on this topic, but it is outdated as the solutions are now different.

Tips for uninstalling first-party apps:

  1. Sort solutions in descending order–that generally tells you which solutions to remove first
  2. Remove patch solutions before removing the main solutions
  3. When in doubt, go to the components list in classic solution manager, select one of the entities in the app and click “solution layers.” This gives you information about the layers, remove the higher layers first.
  4. When you hit a dependency notice when deleting the solution, remove the dependency, then delete the solution.

The following is the order of operations from the video:

  • msdyn_FieldServiceTrial
  • msdyn_FieldServiceGeofencing
  • Remove Geofencing SDK step
  • msdyn_Geofencing_Patch_1
  • msdyn_IoTHealth
  • msdyn_IoTProviders_Patch_1
  • IoTProviders
  • msdyn_CFS_Patch_1
  • ConnectedFieldService
  • msdyn_IoT_Patch_1
  • IoTConnector
  • msdynce_FieldServiceHealth
  • msdyn_FieldService_Patch_6
  • remove msdyn_/Utils/head.js from user form
  • remove msdyn_/Utils/head1.0.3.js from contact form
  • FieldService

Cover photo by unsplash-logoOlga Guryanova

Tip #1314: Sharing in Forms Pro

You create an amazing Forms Pro survey, and you want to share it with your colleagues so they can edit it. So you hit the Share button.

You are given three options: Share and collect responses, share as a template, and share to collaborate. To share editing privileges, you should select Share to collaborate.

This will give you a URL that you can give to your friends, from which they will be able to collaborate on the survey.

So why don’t they see it in the Shared with me area?

The reason your colleague may not see it in the shared with me area is that they haven’t accepted the invitation yet. Once they click the share link once, the next time they log in the survey should appear in the shared with me area.

Cover photo by Stephanie Pombo from Pexels

Tip #1313: Blocked by conditional access

We are back from the travel bursts, some reorganization, and “hold my beer I’m too busy to do it myself” spurts. The first post after this short hiatus is not going to be about Power Automate, however tempting it might be. We’ll get to that subject later on this week. In the meantime, something a bit more pressing.

Imagine you have working code, something innocuous, something perhaps like this fragment:

using (var client = new CrmServiceClient(connStr))
{
  if (client.IsReady)
  {
    Trace.WriteLine(
      $"User={client.GetMyCrmUserId()}");
    Trace.WriteLine(
      $"Org={client.ConnectedOrgFriendlyName}");
  }
  else
  {
    Trace.WriteLine("NOT READY");
  }
}

You admire this bastion of reliability for a second then go get a refill for a drink of your choice. When you come back 5 minutes later, your defenses are crushed and the code stopped working (a.k.a NOT READY message). No, this is not a joke, yes, participants of the Toronto BAD Masterclass witnessed it in real time and yes, it did happen in real life though perhaps less dramatic, just replace going for a drink with going home and coming back the next morning.

The worst part is that the logs won’t give you anything. Even if you enable logging as per Use Trace Not Console nugget of wisdom, you’d get an infamous fault exception at best:

Error: 
An unsecured or incorrectly secured fault
was received from the other party.
See the inner FaultException
for the fault code
and detail.

It does read like a mediocre haiku when you format it like that, doesn’t it?

If you have your own authentication implementation that goes a bit deeper (as we’ve done in our PHP Toolkit), you may get a less cryptic message

AADSTS53003: Blocked by conditional access.

Which is still a mystery – what conditional access? As with any murder story, there are two parts to whodunnit.

Part 1: The diligent

Unbeknownst to you, a curious but, unfortunately, overzealous and not very thorough Azure AD administrator discovered baseline protection policies and, among those, ability to block legacy authentication. “We don’t use POP, IMAP, SMTP, do we” – reasonably argued the admin and enabled the policy.

Turns out, “legacy authentication protocol” is a very broad and not very well defined scope that includes any user-level protocol where MFA cannot be applied. That unfortunately, includes WS-Trust authentication that is widely used by our beloved SOAP client that, as of the time of writing, is still a foundation of the SDK client including CrmServiceClient from XrmTooling.

Part 2: The oblivious

You guessed it – the connection string in the example above was using username/password combination. Perhaps, it was a historical oversight. Perhaps, despite the server-to-server authentication being available for a long time, the coder was clinging to the non-interactive user logins. Whatever is the reason, combined with the shooting in the dark admin, the code fell apart.

It was a hunting accident. Admin was aiming for a sitting duck (or so they thought), the code just happened to be in the line of sight.

Part 3: The solution

Review your code for any authentication that still uses username/password and replace it with the OAuth equivalent. If the process is interactive, use ADAL libraries. If the process is in a dungeon, use server-to-server authentication variation of those. Easiest way to deal with these scenario is to use XrmTooling with its plethora of authentication methods, both interactive and not so.

But whatever you do

STOP USING named Office 365 account for authentication

Tîpp Jäår

If you have Azure AD Premium, you should be able to buy some extra time by adding a policy exception that would let WS-Trust through. I wouldn’t recommend it though – could get messy and it’s better to fix the code, anyway.

Cover photo by kat wilcox from Pexels

Tip #1312: View process history from Unified Interface forms

Tipster note–this tip is an unsupported tip. It’s not going to damage anything, but it is unsupported and may stop working with future updates. Proceed at your own risk.

So you have moved to unified interface, but you want to be able to see the process and workflow history for a record. Microsoft has not yet given us a way to check the process history for a record from Unified Interface, and while you can navigate to classic settings and see the full process and system job history, it is very cumbersome to see it in context of a specific record.

Using the following approach you can display the process history for a record on the unified interface form.

  1. Create an iFrame on your form called IFRAME_Workflows
  2. Create a javascript web resource
var WorkflowIframeSetter = function() {
  function onLoad(executionContext) {
    var formContext = executionContext.getFormContext();
    //if this is CreateForm - let's leave the form blank
    if (formContext.ui.getFormType() === 1) {
      return;
    }

    //Getting entity Metadata to get otc (Object Type Code)
    Xrm.Utility.getEntityMetadata(formContext.data.entity.getEntityName()).then(
      function(entityMetadata){
          var otc = entityMetadata.ObjectTypeCode;
          var url = "/userdefined/areas.aspx?inlineEdit=1&navItemName=Background%20Processes&oId=" + 
            formContext.data.entity.getId() + 
            "&oType=" +
            otc +
            "&pagemode=iframe&rof=true&security=852023&tabSet=areaAsyncOperations";
          
            formContext.getControl("IFRAME_Workflows").setSrc(url);
      });
  } // onLoad function
                
  return {
    onLoad: onLoad
  };
}();
  1. Add to your form

Voilà Process history on your Unified Interface form

Thanks to Andrew Butenko for the script.

Cover photo by unsplash-logoHenry & Co.

Tip #1311: Use entity name in Flow lookups

If you are building your Flows from solutions and connecting to Common Data Service, you should use the CDS (current environment) connector.

When you do, if you populate lookup fields, you might get a “resource not found” error message.

If you get this error, like I did, you are probably just putting the guid of the record in the lookup field. You need to also include the entity name in your reference.

Once you do, your lookup field should populate properly. Thanks to David Yack and Antti Pajunen for this tip.

Cover photo by unsplash-logoWesley Pribadi

Tip #1310: Using Flow to test concurrency

Today’s tip is from Shidin ‘D365fanboi’ Haridas – thank you!

Got a tip of your own? Why won’t you send it to jar@crmtipoftheday.com when you have a minute? Now, over to Shidin.


Most CRM implementations, at some point, would have required to implement a bespoke auto-numbering system.

However, testing the custom built auto-numbering solution end-scenarios, especially involving optimistic concurrency was always the toughest challenge.

Flow can be used to help out testing such end-scenarios of optimistic concurrency:

  1. Create a flow with a loop to create the entity records (in the below example, initialized an array collection to loop through)

Flow to create CDS records in a loop

  1. In the loop control settings, enable ‘Concurrency Control’ and increase degree of parallelism to 2+.

FLow concurrency settings

  1. Now, when the flow executes, multiple records will be created in the Dynamics 365 database at the exact time!!
  2. To verifying this, create an alternate key on the auto-number attribute.

The flow run will fail if the bespoke auto-numbering system tried to insert the same values against the record.

Tîpp Jäår $0.02 + GST

  • It’s been a while since I implemented an auto-numbering system that required testing. Why? Because Common Data Service supports auto-numbering. Having said that, I have seen autonumbering requirements in the wild that wouldn’t fit on one page and require a team of 3 or more software engineers to implement. Those exactly are the occasions where you’d want to test. Or change the requirements. Or job.
  • Don’t restrict your imagination to auto-numbers. There are plenty of other situations where you’d want to test records be created at the same time.
  • Be aware of the Flow limits – those would be very easy to break while doing loop-de-loop.

Cover photo by Pixabay