Launching a new YouTube Channel: Power Platform Clinic

After sometime of doing the research and getting my courage to start recording content for YouTube, I’m pleased to launch a new YouTube Channel called: Power Platform Clinic (

This channel is dedicated to answer questions from the community with a content that I hope to be clear enough and helpful for the broader community to use and learn.

Within this channel I’ve started with the “How-To” series that begins with the How to Configure Omnichannel for Customer Service and the next one that is already in production will be related to the PVA integration with Omnichannel.

Background Story

Note: If you are not interested in story, you may want skip this background story and just go straight to the YouTube channel 😉

The story that I’m sharing here is aimed help/encourage others, who might be in similar position as me, to be encouraged to help/share to the community.

Some of you might know that I have cameraphobia and anything of being recorded. Every time I’m doing recording, I have to gather all my courage. So far I only do few online recordings such as:

Since then I’ve never do any new recording or something similar. Elaiza Benitez and Ee Lane Yu have asked me a few times to be “featured” in their series, but I turned them down, as I’m being so nervous to put myself in front of camera & mic.

In the past few months, as we are in the COVID-19 lockdown and things have move to online meeting, it has become a training ground for me to overcome my fear (at least I’m more used to sit in front of webcam & speaking)! So, it is apparently a kind of blessing in disguise for me.

The second motivation for me to start this channel is that I’m inspired by my dad, he’s a retired doctor, but in this kind of COVID-19 crisis, he has offered himself to be available and become the front-liner to help the patients. In the absence of my medical knowledge and capability, I can only help and contribute to the community with my technical/IT knowledge. Thus, the brand name: Power Platform Clinic is chosen, as I would like as much as possible to give back to the community with answering their question, providing help and/or consultation.

Side note

On a side note of recording my own YouTube channel that I’m going to deliver in English, myself and some friends from Indonesia (special mention: Juneidi Tsai) are also starting to producing Power Platform related content using Indonesian language in our mind to help the local community grow (I was coming from non-English speaking community). If you are Indonesian and would like to subscribe to the other channel please visit: Power Platform Indonesia Youtube channel:


Spelling Checker in the new Editors of Unified Interface

As Microsoft just recently applied the latest update 2020 wave 1 to our instances, which includes an update to the editor to the notes section. Previously, it was using a plain text editor where spelling checker from the browser can interact with it.

With the new rich text editor, when you right click the incorrect text it will now showing the cut/copy/paste options instead.

To use the native browser’s spelling checker, now we need to use CTRL + Click

Hopefully this can help you with the usability of the new control that is available.


Credit to Elaiza Benitez, who pointed out and send the workaround.

Quick Tip: Updating SharePoint Document Location in Unified Interface

I’ve been recently helping a colleague of mine that has a need to change the SharePoint Document Location’s relative URL, as the folder of the record needs to be renamed.

With Unified Interface you will not be able to change the document location from the form that opened up via Advanced Find. You’ll see it “hardcoded” to be read only.

So, for the workaround, I need to open the record by forcing it to be opened in classic, with the following URL pattern:


It will open the window in the classic (notice that it is “Super” classic) form and allow you to make modifications:


Note: I’ve submitted a feedback in the Power Apps Idea site, please upvote 😉

New PCF – TinyMCE Rich Text Editor

So, after learning on how to make a PCF control from my previous learning experience. I decided to look for other controls that I can work on. One of them is the TinyMCE/Rich Text Editor control. I noticed that there is another RTE editor in However, one of my need is to convert them to the HTML content, as it will be used within the body of email in some of the existing workflows, and also the existing system that I’m working on is already using the older xrmtinymce that hasn’t been maintained for a while.

Without further ado, here is the demo:

You can check the source code and get the managed solution from this github repo:

A few learning items from building this PCF control:

  1. If you are running older node.js, please update it. I was running v.9, and the current stable/recommended one is just recently updated to v.12 from v.10 last week. When, I was running the older version and I run into an issue when I’m trying to include the tinymce css.
  2. To include external libraries, I can’t customise the webpack of PCF CLI, for time being, I need to add them all as resources in the ControlManifest.Input.xml

My First PCF Control: AddressFinder Australian Addresses

First of all, credit to Sankal Bansal on his New Zealand Version of the similar control with the same provider.

I was recently working on a specific task to implement a new Address Autocomplete/Validation solution. So, the selected validation/provider was AddressFinder. This API provider provides quite extensive information that the typical Australian addresses need (GNAF ID, DPID, Geolocation, and some more IDs provided as the metadata).

Traditionally, we create an HTML web resource that interacts with the main page script. But then the roadmap ahead is going towards building PCF controls. So, I decided to give it a go on building this PCF control.

To begin my journey, I was looking at and found some good examples of address autocomplete with Azure Maps & Google Maps. I learned the concept from those examples, then I found Sankal’s solution that is almost the same as what I would like to achieve. However, his solution is based on New Zealand’s dataset (metadata and mapping are different) and doesn’t map the full address to a field.

So, I created a specific Australian solution for this PCF. You can find the detail at my github repository:

The workaround to get the mapping is to follow this post:, as this is a known issue with the PCF:

A quick demo here:

Dynamics 365 Portal – Authentication Deep Dive (Part 4) – Tips & Tricks

Finally, after quite hectic months with all big events are happening in Melbourne, Australia & Globally (Dynamics 365 Saturday, UG Summit and Global Hackathon), I’m going to finalise this series of authentication with Dynamics 365 Portal or should we call it PowerApps Portal now 😉

So, without further ado, here are some tips & tricks in authentication implementation for Dynamics 365 portal:

  1. Set Login Session Timeout

As part of the security policy sometimes we need to set the login session timeout. When I was trying to configure this, usually the Identity Provider will have the configuration of the token lifetime.

So, my first thought was to use the Open ID Connect settings to set the cookie timeout: “Authentication/OpenIdConnect/[provider]/UseTokenLifetime

Well, after some testing, that doesn’t change the timeout. So, to properly change the session timeout apparently, I need to set the following configuration:


  1. Use default Login Provider

When we configure the external login, sometimes it is a specific direction, to only allow a specific login method for the portal audience. To achieve this, you just need to set the following configuration:

Set the value as the same value of the ‘Authority’ of the Authentication Provider URL is:

e.g: if your “Authentication/OpenIdConnect/[provider]/Authority” is “” put the same value on this setting. This will “force” the login process using the specified provider.

  1. Claim Mapping – Resolve basic contact mapping

When we configured the external Authentication Provider, once we are able to login, usually it will prompt us with the email, then creating new contact record if the record doesn’t exist, or it will complain about the duplicate contact exist and stopped the process, which sometimes frustrating and causing orphaned records…

So, to make it a more seamless experience:

  • Set the “Authentication/OpenIdConnect/[provider]/RegistrationEnabled” to true
  • Set the “Authentication/OpenIdConnect/Auth0/RegistrationClaimsMapping” to reflect the mapping. Commonly we would like to set the First Name, Last Name and Email Address: “firstname=,lastname=,emailaddress1=”

More detail of the claim mapping:

And the options on what we can use from the identity provider:

  1. Force Login when accessing pages other than the Home page

In my recent scenario, there is a requirement to make the other web pages not available for non-authenticated users. I can apply the “Authentication Required” on each page on my site. However, this is not an efficient process. In particular around the maintainability of the portal. So to achieve this in an efficient way:

  • Navigate to Web Page -> Home
  • Navigate to the Access Control Rules section
  • Create a new Rule as follows:

Web Access Control.png

Make sure you select to the scope to Exclude direct child web files, otherwise the portal scripts and css will be blocked as well.

  • Add the “Authenticated User” under the Web Role:

Auth Users.png

That’s all the tips & tricks related to the Dynamics 365 Portal authentication. I hope this helps!

Dynamics 365 Portal – Authentication Deep Dive (Part 3) – Using the Third Party Auth Providers

In the previous post, we have discussed how to configure Azure AD B2C using the Open ID Connect method. One of the challenges that I had in my past experience is that the client has a strict requirement of data residency, due to the sensitivity of their business. Therefore, they are considering some 3rd party options that have their solution deployed in Australian data centre. Some of the options that we have explored are Auth0 and Okta.

The same principle of configuring Open ID Connect authentication, these 3 site settings records need to be created & configured:

  • Authentication/OpenIdConnect/[provider]/Authority
  • Authentication/OpenIdConnect/[provider]/ClientId
  • Authentication/OpenIdConnect/[provider]/RedirectUri

Note: The key part of configuring authentication always be getting familiar with the product and how to find the right equivalent information 😊

Example of 3rd party External Identity Provider: Auth0

First of all, we need to make the “Application” as the container of our configuration in Auth0 management portal.


Select the Regular Web App option (this will have pre-configured settings for the auth token required for the majority of web apps).


Register the Allowed Origin and Callback URL(s) of our portal site. Mine is like below:


Take note of the client ID to be used for the portal configuration:


Expand the Advanced settings, take note the OAuth Authorization URL, this will be the value of “Authentication/OpenIdConnect/[provider]/Authority”


Configure the site settings to have the following items:


Quick Demo:


Example of 3rd party External Identity Provider: Okta

Similarly, when configuring Okta, need to set up the application as the container of our web app authentication configurations.


When creating the application, select the Web application


Configure the base URL, login redirect URL(s) & the Grant Type. I choose the below option (mimicking the Auth0/Azure AD B2C settings). Also, take note of the client ID.



To find the “Authentication/OpenIdConnect/[provider]/Authority” value, navigate to the API section and take note of the issuer URI


And add the Portal Base URL as the allowed/trusted origin


Then finally set up the site settings as below for Okta Auth:


Okta Auth Demo



I hope the flexibility of the Authentication framework that the Dynamics 365 Portal offers would help you to be able to leverage your existing IDP/Auth provider to connect to Dynamics 365 Portal easily.

In the next post, I will discuss some tips & tricks to get a more seamless end-user experience authenticating to the portal.

Hope this helps!

Dynamics 365 Portal – Authentication Deep Dive (Part 2) – Using the Microsoft Azure AD

The second part of the series of the blog post is to leverage the Microsoft Azure AD capability to deliver the authentication capability for the Dynamics 365 Portal.

There are 2 parts of the Azure AD that we can use depending on the audience:

  1. Internal-facing Portal: Azure AD
  2. External-facing Portal: Azure AD B2C

Now, let’s walk through the detail on each part.

Azure AD Authentication

The Azure AD authentication use case is predominantly for internal users such as employee or contractors accessing an internal company’s portal, such as employee self-service portal.

This feature is enabled by default for Dynamics 365 Portal with this specific Site Setting to look for:


This will provide seamless authentication for all internal users.

How about guest users, such as contractors or partner? Azure AD provides the ability to invite Guest Users via the Azure AD B2B.

Azure AD B2B use case would be for the Partner Portal functionality.

To enable the guest user access, we first need to have the user added in Azure AD as “Guest User”

Guest User.png

In this example, I’m going to add my work account ( to my personal instance ( Once invited, I’ll receive the invitation, click on the Get Started to “redeem”/confirm the invitation. You’ll notice that you don’t have access to any application, but that is fine.


Once confirmed, I now can login to the portal by clicking on the Azure AD login method using my work (external) account.

Note: If the Azure AD is configured using Federated auth with AD FS, the Portal Azure AD auth also will use AD FS.


AzureAD B2B.gif

External facing portal with Azure AD B2C

Azure AD B2C is the option for external users, typically for the public facing portal, such as customer self-service, community portal or partner portal.

Note: at the time of writing this article, Azure AD B2C deployment does not include some regions like Australia:

The good news for Australian-based users, Dynamics 365 Portal Authentication is only using Azure AD B2C for the user object ID and securely storing the login credential, PII and other profile information is stored in Dynamics 365, which is hosted in Australian Data Centre.

To implement Azure AD B2C authentication, I would recommend using the Open ID Connect authentication method. This is the commonly used authentication method that is available from most of modern ID/Authentication providers. So, to begin with, there are 3 main Site Settings that you will need to pay attention to enable any kind of Open ID Connect authentication:

  • Authentication/OpenIdConnect/[provider]/Authority
  • Authentication/OpenIdConnect/[provider]/ClientId
  • Authentication/OpenIdConnect/[provider]/RedirectUri

The [provider] part of the settings should be replaced by the name of the authentication method/provider that you would like to name (this also become the display name of the authentication button at the sign in page).

From the Azure AD B2C perspective, once you’ve created the Azure AD B2C deployment, you will need to add Dynamics Portal application to the list:

Application Reg.png

Create the application, make sure that the “Allow Implicit Flow” set to Yes. Reply URL should be in the format “[portal domain]/signin-[Federation-Name]” (Ref:


Once the Dynamics Portal application added to AAD B2C application, you’ll need the ensure to set up the user flows/policies:

Policy 1.png

At least configure the Sign in and Sign Up & Password ResetSign-in Policy 2.png

In particular, on the Signup and sign in policy, set the bare minimum information for the claim, such as email address, first name and last name and keep the rest to be managed in Dynamics 365 (unless you would leverage the full capability of Azure AD B2C to manage the profile). The tips & tricks on configuring the claim I’ll discuss in the next posts.

Once configured you will need to grab the 3 most basic information: Authority, ClientId and Redirect Url.

To find the value for the “Authority”, open the Sign up and sign in policy that you’ve created and click on Run user flow:


It will open a panel, click this well-known/openid-configuration link to see the JSON metadata:

AAD Authority.png

And grab the value from “issuer” to be value for the Authority.


The value of ClientId is the GUID of the application that you created in the previous step:


And RedirectUri is the from the Reply URL that we set in that application


Once configured, you will be able to sign in using users that have been registered in the Azure AD B2C:

Azure AD B2C Demo.gif

Hope this helps. In the next post, I’ll discuss using some 3rd party identity providers as the alternative of Azure AD B2C.

Further Read: 

Dynamics 365 Portal – Authentication Series (Part 1) – The Basics

I’ve been recently deployed a quite complex Dynamics 365 portal solution involving a custom authentication provider and other features such as Power BI Embedded and SharePoint integration.

In this series, I’ll discuss in more detail about the authentication side based on my lesson learned out of this challenge to get them working properly. My plan is to discuss the following topics in this series:

  1. The basic – Local Auth
  2. External Auth – Using Azure AD & Azure AD B2C
  3. External Auth – 3rd party ID provider
  4. Some tips and tricks around

Before we begin, I would admit that I’m not a portal expert, I learned the concept and knowledge from these great experts: Colin Vermander, Nick Doelman, George Doubinski and Dileep Singh. So, credit is to my great “teachers”.

So, to begin with, let’s try to understand the authentication methods that the Dynamics 365 portal supports (

In a nutshell, Dynamics 365 portal’s authentication is based on the ASP.Net Identity, which is based on the OWIN Framework (The OWIN framework is the “jargon” that seems to be commonly being used by the auth provider in their documentation, so always good to know and understand how it works/behaves).

There are 2 methods of authentications in Dynamics 365 Portal:

  1. Local Authentication

Purely based on Dynamics 365 Contact record to store the authentication details.

  1. External Authentication

Utilising the ASP.Net Identity API to integrate with the external ID providers using either OpenID Connect or OAuth or SAML.

To ensure the portal authentication to work properly, ensure the following solutions exist in the environment. These solutions typically will always be there after the portal instance being provisioned, but I had a case where the overall authentication process is not working properly due to missing one of the following solutions (if you encountered the same issue as me, log a support ticket and the support team can add the missing solution fairly quickly).


The minimum viable option of the authentication would be using the local authentication. However, I would recommend to minimise the usage of the local authentication method and use External Authentication (if possible Azure AD-family) as much as possible, not only for the security compliance but also future proofing your portal investment. This is based on Colin Vermander’s blog post from last year:

Even though the link in the article is no longer showing the deprecation on it, but I reckon the intent to push to Azure AD B2C is still there.

Local Authentication in a Glance

When you are using the Local Authentication, the portal solution is storing the user creds within the contact entity. Password is stored as hashed text within Dynamics 365 (even though Dynamics handles the security and encryption at rest, this could be an “alarming” thing when the system is being audited by security experts. Thus, recommended to use external idp).

username password.png

Some of the notable site settings that construct the basic behaviour of the local authentication in Dynamics 365 Portal:

  • Authentication/Registration/Enabled
  • Authentication/Registration/LocalLoginEnabled
  • Authentication/Registration/OpenRegistrationEnabled
  • Authentication/Registration/InvitationEnabled
  • Authentication/Registration/RememberMeEnabled
  • Authentication/Registration/ResetPasswordEnabled
  • Authentication/Registration/ResetPasswordRequiresConfirmedEmail

The technical description of those settings are available in this documentation article:

In the next post, I will discuss on how to configure the authentication using Azure AD & Azure AD B2C.

Update to the Unified Interface in the October 2018 Release

Microsoft product team just shared the latest update for Unified Interface in the October 2018 release. This is important especially for those who have started embracing Unifed Interface in their organisations. Note: These Unified Interface updates were not highlighted in the October Release Notes and there is no official article/documentation that stating this yet.

Overall, the update is to address the feedback around the usability and adoption of Unified Interface, primarily around the navigation and colour scheme. To keep in mind, this update is going to be automatically applied to the organisations with v.9 onwards, without the “Opt-In” feature (Related to the quite recent announcement from Microsoft about the continuous update of Dynamics 365). It means if your organisation has embraced the Unified Interface, there might be a slight change to the training material (if any) and preparing communications to the end users so that they are aware of this UI/UX change to the Unified Interface.

The changes are as follow:





Sitemap changes:

  • Site map will be expanded by default, with the option to collapse, to improve user recall and learning.
  • Simplified IA: MRU (recent) and favorites (pinned) moved to top level, always visible. No more entity level MRU.
  • No more tabbed sitemap. Bottom flyout used to select areas. To reduce icon overload, colorized tiles replaced area icons.
  • New color scheme (black on gray) to improve navigation discovery.

Commanding changes:

  • Dark text on light background to group commanding with the content area it effects
  • New colored icons and hover effect distinguish different commands and highlights interactive regions

Affected viewport width
These changes are aimed at improving user experience for desktop browser users at widths above 480.

Leveraging Microsoft Flow to be your API Engine – Low Code Approach

Recently I’ve been experimenting with Microsoft Flow and its counterpart, Logic Apps. A thing that I noticed could become a game changer in designing a business solution these days is that Microsoft Flow can be turned into an API engine. In my example, I’m going to create a very simple API to send a message to my Skype for Business and reply back with the response whether the API call is successful or not.

The first step is by registering the HTTP Request trigger in the Flow step:


As any typical API, you will need to specify the data payload. To generate the payload schema, we can use the “Use sample payload to generate schema”. I’m going to use a simple payload to send the message:

      “message”:”payload for skype”
Once generated, this will create the schema for you
To ensure that the payload schema is validated on the HTTP request by clicking the Settings option:
And turn the Schema Validation to On
The next step is to register the action that you would like to perform (you could be creative here with the available connectors for Microsoft Flow or you can come up with your custom connector).
In my sample, I’m going to add the Skype for Business action: Send Instant Message
As any typical API, we will need to provide the response appropriately. In this example, I’ll just implement the success response. Exception handling will be discussed on a separate blog post.
Once finished, save the flow and the HTTP Request step will generate the API endpoint:
To test the endpoint, you could simply use Postman (or any tools to stimulate HTTP request) to trigger it:
And here’s the result:


To create a low-code API is now become very simple with Microsoft Flow. With the available connectors and actions, workflow-based API can be achieved in configurations!

Business Apps. October ’18 Release Highlights

Microsoft just announced the October’18 Release Notes from the last week’s Business Application Summit conference at Seattle. The first question that might come up is: Why October, aren’t we still in July and October is still 3 months away? The answer is in response to the recent blog announcement about the way Microsoft Dynamics 365 will be updated: The release notes are made available upfront to allow customers/partners to be familiar to what is coming and plan ahead with the updates.

Now, the official article of the release notes can be viewed here and the actual release notes can be downloaded here. So, after spending the weekend of reading the 239 pages of the release notes I would like to list the highlights of this updates, in particular to the Dynamics 365 CE, Flow and PowerApps. Sorry, ERP-counterpart of the Dynamics 365 family, and Power BI, I’m not the expert on that.


So, without further ado, here are the highlights of this October update from my perspective.

Dynamics 365 for Sales

  • Playbook – Seems to be a useful feature, if this can be extensible
  • Microsoft Teams integration!
  • Dynamics 365 AI for Sales Rep… oh WOW!

Dynamics 365 for Service

  • Omni-channel engagement hub
  • Channel Integration Framework – aka bring your own channel
  • BYOB – Bring your own Bot!

Dynamics 365 for Marketing

  • Segmentation enhancement – more operators and hoping for the performance is really bumped up
  • Custom analytics – the current release of Dynamics 365 for Marketing only provides the “Insights” that come from the OOTB package, with this Custom analytics enhancement, really hope that we can create tailored insights, and seems it will open up Power BI reporting

Dynamics 365 Portal

  • Portal Config migration – schema is now going to be provided
  • Embed Power BI on Portal!
  • SharePoint Integration is back!! – oh wait…


  • Adjustments to approved items! – my wish-list is apparently being implemented 😉

PowerApps & the D365 Platform

  • Embedded canvas app on D365/Model-Driven PowerApps
  • Choose your own size app – closer to the “Pixel-Perfect” slogan
  • Create Canvas Apps with responsive layout – finally!
  • More “integrated” look of Model-Driven PowerApps – within PowerApps studio, instead of the “jumping” experience with the Dynamics 365 CE
  • Improved ALM – looking forward to this!
  • Dependent Option Set – doesn’t tell whether this is for Canvas App only or for Model-Driven Apps as well? If yes, this is awesome!
  • Solution checker – this features from high-level seems to be awesome. Similar to the reports that the PFE guys used to produce 😉
  • Missing features like advanced find, merge records, run reports, run workflows and bulk edit are available in UCI (Model Driven PowerApps)

Microsoft Flow

  • Design Microsoft Flow using Visio – yay! Caveat: need Visio Online Plan 2.

What to expect?

With the above highlights and referring to the “caveat” of the release notes: “Features Releasing from October 2018 through March 2019”, all we can do is to wait and see the update waves to land 😉

Troubleshooting: “There is no active transaction” Error.

Today I encountered a very weird error when I’m working with my team to create a very simple workflow, on a status update, if the status is equal to a specific status, create a task that is assigned to a specific team. However, we can’t proceed due to a very strange reason:


This is the error message:

“There is no active transaction. This error is usually caused by custom plug-ins that ignore errors from service calls and continue processing.”

So, I googled it to find the similar error. Based on a past post by Aileen:

We have tried checking the suggested approach by her:

What to Check

So, if you find this error, please check:

– Whether you have custom plugin/custom workflow active triggered
– Whether you put skipping the error that will have impact to the CRM process, it is not possible
– Actually you better to log the error
– Because you won’t know what it is
– This is not your logic wrong in your custom plugin
– This just you need to fix why CRM cannot proceed?
– Is that because your user/team does not have privilege or you missed some parameters required
– This error might happen like for Assignment, Lead Qualification, Quote creation, etc

However, no luck 😦

And we also come across this forum discussion:

where some people are mentioning about an issue with ActivityFeeds plugins, again no luck, as we can’t find the specific ActivityFeeds plugins registered.

So, as the usual troubleshooting technique of elimination process, we tried to remove 1-by-1 the workflow mapping, and we found the culprit. Apparently, it’s on the mapping of record owner in the Create Task step. For some reason, if we set the owner on the creation of the task, it keeps throwing the error. So, we split the owner assignment to a separate step to assign the record to the team. Something like:


And it solves our misleading “Custom Plugin” issue.




TIL: Do not use ExecuteMultipleRequest in Dynamics 365 Plugins/CWA

Today I learned a new thing about ExecuteMultipleRequest within Dynamics 365 plugins and/or custom workflow activities. The following article: suggested that we should avoid any usage of Batch Request in server-side codes.

Background story

My colleague reported that when he is using ExecuteMultipleRequest within the plugin, it is throwing an SQL Timeout error, while he changed it to the single request model, the plugin runs fine.

In the past, I always consider it as the go-to model, when I need to perform multiple requests like creating/updating multiple records. And I used to use this ExecuteMultipleRequest to log exceptions to Dynamics 365 records in the past (according to this MSDN article:


The Truth

Now I learned that ExecuteMultipleRequest is not designed to be used within server-side codes such as Plugins and CWA. Reason:


The design of batch pattern is to reduce the lags due to the network latency (the application is performing HTTP request to the Dynamics 365 API). Where having the code running on the “same” network is defeating the purpose of the design.

Another reason:


There is a throttling limit on the batch pattern, by using the batch request in plugins, it is unnecessarily reducing the available “slot” for the concurrent bulk request to run.

Final Remarks:



Microsoft Flow: Creating Dynamics 365 Scheduled Report – Low Code Approach

Recently I’ve been exploring the power of Microsoft Business Application Platform. One of the most common requirements that I think we can solve in the Low Code Approach is the scheduled report.

For this example, I’m going to use this example user story to describe the scheduled report requirement: As a sales manager, I want to receive a daily digest of the new opportunities, so that I have the visibility of new opportunities in my organisation.

Before thinking about the solution, we might need to look at the platform that we are working on right now. Microsoft Business Application Platform, where Dynamics 365 plays an integral part in it, comes with Microsoft Flow that has numerous connectors available. This opens up a very broad capability in building the business workflow.

So, without further ado, here is my “Low-Code” approach generating the scheduled report (if you want the more complex one using SSRS, Bob Guidinger, has the solution here).

The first step in the Flow is to set the schedule:


Next, we need to construct the filter for the Get List of Records from Dynamics 365 oData query, to build it I’m using Jason Lattimer’s CRM Rest Builder 


Once the query is generated, copy the filter as the base to be put in Flow


To get the created on = yesterday, we could use the Flow Built-In Formula/Expression:


You also could try the query whether it’s successful or not by running the Test process on Flow


This will need a bit of Dev knowledge to understand the JSON output of the list records, but we can confirm that it is returning the list correctly or not


Once confirmed, then we can construct the HTML table for the email body using the Create HTML Table action on Flow and to some field mapping.


And then send the email action:


Make sure that to select the Is HTML to Yes, otherwise, the HTML tags will be rendered as literal text


This will produce a very basic email, that tick the box of the requirement, but not pretty


So, to make it more appealing, I’m adding the “Low-Code” CSS to style the table using the compose action before sending the file


Attribution: CSS is a copy from w3schools:

Now with the CSS, the table is looking more appealing


Another ask, can we also have this table/report as HTML. The answer is Yes. Microsoft Flow has connectors to convert HTML to PDF via 3rd party service such as Muhimbi PDF or Plumsail Documents (which requires subscription/license)


The quick and dirty option to save to PDF is via OneDrive actions, by creating the HTML and Convert the file to PDF.


Typically you could create a folder in OneDrive to store the report temporarily and do periodic clean-up.

Then this can be added to the email as an attachment:


Which produces the email with the PDF attachment:


And the PDF file opened with PDF reader:


My Final Flow is something like this:



HTH! Happy Flow-ing!

Gotcha: Don’t Use Nested Security Group

Some time ago, I published a blog post about a tip about using Security Group in Dynamics 365 Online Deployment. And I’ve got a feedback from one of my colleagues where the security group is not allocating the users properly. So, I investigated the behaviour with my colleague and found an interesting setup.

TL;DR; version: Do not use Nested Security Group, as Dynamics 365 would not honour it.

The Long Version

So, I noticed in my colleague’s environment they have set up nested security group. To explain, I’m going to “replicate” the scenario in my environment.

I have set up my sandbox environment to use “Dynamics Sandbox” security group as follow:

Sandbox Security Group.png

And the Dynamics Sandbox security group has membership as below:


“Dynamics Test” there is the child group that I have setup with the following members:

Child Group.png

Normally, When I have a nested group like that. I would expect Test User 2 – 5 will also be included in the Enabled Users list. However, this is the result:


To ensure the rest of the users are synced to Dynamics 365 the group must be flattened:


Then, you’ll be able to see them in Dynamics 365.


I have confirmed the behaviour with the Microsoft support, that nested group is not supported at this moment.

Hope this helps!

Dynamics 365 Online Deployment Tips: Set Your Security Group!

The feature of Security Group in the Dynamics 365 Online deployment has been there for a while. However, I often find either people do not understand it correctly or this feature is not being considered as an important “checklist item” for a smooth deployment. So, in this post I will share some reasons on why we need to plan setting up the security group.

To support the example, I’ve set up the following scenario:

In my instance I have 4 users:

Users List.png

And 2 Security Groups for Production and Sandbox

Security Group.png

Where in Production, everyone is the member of the group:

Prod Membership.png

While in Sandbox, Test User 3 should not access the environment

Sandbox Membership.png

Now, let’s begin with the reasons why we need to implement Security Group.

#1 For Authorisation Purpose

In typical Dynamics 365 implementation, there will be multiple instances, such as DEV, TEST, UAT and PROD. When the instance has been associated with the security group, only users that are member of the security group can access the environment. The traditional way to restrict access by not assigning the security role to the users is still viable, but this leads to the reason #2 below.

The difference on the error message would be as follow:

  • Not assigned with the security role


  • Not part of the Security Group

Not Part of Group.png

#2 To Keep Users in the Instance Clean

On top of the first point, to prevent the users to access the environment, having security group configured for the environment will also prevent the users that are not part of the security group to be synchronised with the environment.

A thought come into my mind: it won’t harm right to have the users synced. As long as, we are not assigning the security role to them. Yes, it’s true from the authorisation perspective. However, having them in the environment that they are not supposed to be, also means they will be under the list of “Enabled User” that can be used in selection when assigning records. In multi-organisations deployment, it also means the user from different organisations are visible to the environment. These situations could cause confusion to the users.

The list from Production environment:


The list from the Sandbox environment:


#3 To Hide Unnecessary Items at the Apps List/Instance Picker

With the “App” concept in Dynamics 365 Online, the will contain all kind of “Apps”. This includes the Apps that deployed within the instances. When a user have the privilege to access multiple instances, they also will see the “Apps” that are deployed in those instances. IMHO, it is always the best approach to hide anything that users should not see, so that they could focus on what they need to do with the system.

For example, my user that has full access to all environments, could see the following:


Meanwhile, the Test User 3, can only see 1 “App” that is associated to the instance that this user has access (controlled via the Security Group).


The same thing with the Instance Picker (this has been superseded by the However, if users might have bookmarked this page.

The following is the list from my user:


Meanwhile, this is from the view of Test User 3.



Implementing Security Group for Dynamics 365 implementation should be considered in the design and planning to ensure proper and robust security and user experience.

Hope this helps!



FetchXML Trick – Cross Entity Criteria in a Group Filter

Recently, I had a tricky question: Can you create a view that is displaying records that are either owned by a team or the users that are a member of that particular team.

EDIT: Jonas Rapp provides a feedback to get more efficient with his tool 😉

The TL;DR; Answer

Use “Alias” + FetchXML editing using XrmToolBox (View Designer + FetchXML Builder – this is the one stop shop!).


The Longer Answer

The typical answer to the above scenario would be querying the record with the criteria as “Owner ID = the team OR related Owner (user) is a team member of the team”. Using the Advanced Find query, typically this is the query…


However, it seems we can’t group the “main” criteria and the Linked-Entity criteria. Looks like we are stuck here… Worry not, there is a trick for that. So, before I go to the solution here are some setups to set the background.

I have 3 users in my instance:


And I’ve set 2 teams for the testing purpose:

Team A with myself and Test User 1 as the member.


And Team B with Test User 2 as the member.


Now I have some records for testing purpose:


So, when based on the query to see the Team A records, I would expect to see 3 records there. Using the initial query (above) will return no result, as it is treated as ‘AND’ operation.

To get the FetchXML correctly, I need to edit the FetchXML, my go-to tools for this would be XrmToolBox‘s FetchXML Builder.

To start with, I’ll export the FetchXML out of my initial query, it will look like this:


Now the trick is to use the “alias” of the related team entity to form the FetchXML like this:


As you can see above, we are able to set the condition in the “main” filter and set the operator to OR. Below is the result of the fetch… it works as expected 🙂


Now, I want to put the query to the view, how to do that?

I’ll use XrmToolBox’s Fetch XML Builder to modify the FetchXML of the view. In my case, I’ve setup a Test Query view. Click on Open View….


And then select the corresponding view:


Copy & Paste the FetchXML that we had tested previously into the FetchXML window, if you wish, you could test execute the query. Then click on the “OK” button down there and then click on the “Save As” button up there and save it back to the view.

Save As.png


And here’s the result:




Dynamics 365 Portal – When the Custom CSS won’t load.

Recently, I’m working on a demo that I need to skin the Dynamics 365 portal to have a look and feel based on the client’s theme. One of the pages is the dashboard/landing page that showing some charts.

Let say the URL of the page is called “Dashboard”.dashboard.png

It’s showing up the chart nicely. However, I would like to hide the out of the box chart title, as it seems always giving me a static name (based on the chart name in Dynamics 365, where sometimes I would like to label it to something else).


My approach is to hide this using CSS (display:none;). So, the usual way I change this is by opening up the Web Page record and add the CSS under the Custom CSS part of the web page.Web_Page_Custom_CSS.png

However, it doesn’t change the layout and even after I reset the cache from the “/_services/about” page of the portal.

My problem was solved by editing the web page via the portal itself. So, I navigated to the page, click on Edit and under the Options tab, I add the CSS there.


Once I’ve used this part to set the CSS, now the undesired element is gone.






Just Some Tips Working with Virtual Entities

Recently I spent some time working on Virtual Entities, one of the new features in Dynamics 365 v9.0. To learn more about Virtual Entities, you can read the official documentation here and how to set it up here. In this post, I would like to share my tips and findings working with Virtual Entities and connecting it to a custom oData v4.0 Web API.

During my attempt setting up Virtual Entity, I encountered a very generic error: “Entity could not be retrieved from data source.” for different problems.


The error message is not that descriptive and doesn’t provide further information for me to troubleshoot. I’ve submitted a feedback for this, if you also encounter the similar issue:

The tips in this post hopefully can be helpful to fix the above issue 🙂


So, to set the context, in my sample scenario I have a custom oData data source with metadata as below:


Tip #1 – Make sure the path is in the correct case (Upper/Lower)


I was under an assumption: oData seems to be just an URL, so if I throw in the path as all lower case it should be fine…

Well, one of the reason the error being thrown is because oData seems to expect case sensitive path. I entered “movies” instead of “Movies” and in the field mapping I put “rating” instead of “Rating”. So, make sure the mapping and path is the same as the metadata.


Tip #2 – Missing Field Mapping

In my experiment, I created a few extra fields that doesn’t match the metadata definition. Well, this should not create any harm right, just like other custom entity…

Apparently, when there is a missing field in the mapping, the virtual entity is showing the above error.

So, make sure you have the all fields to be mapped correctly and do not create any field that is not in the oData definition. Luckily, you can still omit fields that you don’t like (e.g: when I don’t have “ReleasedYear” field, the VE still works fine).


Tip #3 – Setting Field Requirement(s)

If you noticed my oData definition for Rating field, it is mentioned there: Nullable=”false”. If the oData set up the field to be mandatory, the corresponding field in the VE also need to be set “Business Required”VE-Field Requirement.PNG

Tip #4 – Be Careful with the “Numbers”

In my oData definition, I have the Rating field, which is a decimal field. But how about in Dynamics 365 we want it to be stored as a different field type, whole number or float instead? Well, VE doesn’t support that, so we need to ensure the field data type is the same from the data source to the VE’s field.

VE-Data type.png

That’s all for today. Hope this helps!

Dynamics 365 v9.0 Hidden Gems – #2 Configurations for a better UX

I’m continuing the hidden gems series of the Dynamics 365 v9.0. Today’s topic is about the UI/UX Configuration that is introduced in the Dynamics 365 v9.0. This is not about the “Hub” features that you can use the custom control, that would be a separate topic on the unified client. The configuration options that I’m going to share here is about the refreshed web UI.

Configuration Option #1: Multi-Select Option Set

It’s been a long waiting ask from the Dynamics Community to have multi-select option sets. In the past, workarounds for this are either using Many-to-Many relationship or flatten the selection within the entity. With this new enhancement to the platform, we can tailor the UX of the data entry to be simpler. The old workaround using Many-to-Many relationship requires the user to click the (+) button at the subgrid and it will pop-up the lookup window to select (lots of clicks here)


Compared to the new Multi-Select Option Set, where we can capture the data in a single location and less clicks.


Findings on the multi-select option sets:

  • Behind the scene, it is stored similar to the regular option set (a pair of value and label), which is good for reporting, it is not stored as just plain text, separated by comma or a specific character that makes it harder to report.
  • We are not able to update existing option sets to be multi-select option sets.

Configuration Option #2: Colour-coded Sub Grids

Another UX enhancement that we can apply with the v9.0 is around the Panel header color for Subgrids. In my example, I’m colour-coding case subgrids under account entity to be able to see open cases with the account by glancing the colour coded cases by priority.


The end result is:


Configuration Option #3: Allow Text Wrapping

In the past, it is another common feedback when we are configuring fields on the form, some of the fields are a bit more descriptive than the other. When it’s longer than the pre-defined label width within the section, the text will be truncated. The almost immediate feedback from the end users would be: I want them to be visible!

With the update of v9.0, the Web UI addressed this feedback to a certain degree. There is an option under the System Settings to allow text wrapping in form fields labels and value.

Allow Text Wrapping.PNG

So, I gave it a go and see a long text label for a single-field text. And it wrapped up to a few lines, which addresses the common feedback. yay!



From my perspective, these configuration options to the UI are giving some improvements to the usability and UX aspect of the application. With simple change and minimum effort, as well as doing it in a supported way, we can improve the UX of the system.


Dynamics 365 v9.0 Hidden Gems – #1 Autonumber

The Dynamics 365 v9.0 for the online deployment has become available since a few days ago. I believe we are all excited with this new release. There are major improvements in a lot of areas such as the unified client (a.k.a refreshed UI and great potential ahead), platform enhancements (Virtual Entities, Microsoft Flow integration directly from Dynamics 365), Hubs – this was the Interactive Service Hubs, being extended for other modules (Sales, Service, Project Service, Field Service) and many more.

Yet, there are few hidden gems that can be uncovered from the v9.0 update that could be a life saver in the Dynamics 365 projects. I’m starting the v9.0 Hidden Gems series to run through the hidden gems. I’m going to start with the first one: Autonumber. And no, this is not the same Autonumber that is available for some of the out of the box entities like case, invoice, order, etc

not the autonumber.png

This feature was announced by Matt Barbour at Microsoft Ignite Conference, the recording is available at this Youtube video. At this moment, this feature is available from the API only and there is no explicit documentation available yet.

At high level, this Autonumber features could generate the number with below features:

  • Date format
    • Syntax: {DATETIMEUTC:[format]}
  • Sequential Numbers
    • Syntax: {SEQNUM:size}
  • Random String
    • Syntax: {RANDSTRING:6}
  • Static string
    • Any string component that is not using the above syntax will be treated as static string.

Sample code snippet from Matt’s presentation:

Autonumber code snippet.png

Given at this moment the documentation is not available yet and it is only available via the API, this is a bit tricky for Admins/System Customisers to work on this feature. Luckily, the Dynamics 365 community is really reactive to this and there are few helper tools available.

Option 1: AutoNumManager – XrmToolBox Plugin by Jonas Rapp


You can read the instruction on how to use it at: and download the plugin from GitHub:

Option 2: Easy AutoNumber by Dimitri Chevkov

Another option if you would like to configure the Autonumber from the Dynamics 365 itself. This solution is provided as Dynamics 365 managed solution:



So, I’ve tried the Autonumber features and would like to share some of my findings here:

  1. This autonumber attributes apparently more robust from the Workflow/Plugins workarounds that some people might have developed. It could handle a good degree of parallelism. My PoC was using KingswaySoft to load 5k contact records with bulk operation enabled and using balanced data distributor to do 2 parallel runs. I cannot find any duplicate number with this testing. While the other Workflow/Plugins workarounds produced duplicate records on Dynamics 365 Online environment.
  2. A common question that often been asked by customers: can we specify the starting number? The answer is yes. I looked at Jonas’ XrmToolBox plugin and there is a field to fill in called “Seed”. Here you can specify the starting number for the sequence. Note: from Jonas’ blog post, modifying Seed could potentially generate duplicate numbers.
  3. Multiple Number Sequence within a single Autonumber field is not possible. It seems it is using the same “counter”.
  4. It could not refer to other values within the entity or related entity, where some of autonumber requirements asked for the number to be sequential based on the parent entity. E.g: Custom Case numbering with parent child case, where the child case should use the parent case number as prefix and add the sequence at the end).
  5. At this moment there is no known way to update existing “bespoke” autonumber fields to use this autonumber feature. I read Jonas’ experiment and it seems there are some placeholders within the entity metadata where the autonumber definition is stored. And it seems a bit risky to re-engineer the existing field with something new. If organisations would like to leverage this new autonumber feature, they might consider using a new field, which might impact existing reporting/integration.



Hide the Dynamics 365 script error pop-ups

A colleague of mine recently mentioned that one of our clients is complaining about the script errors that keep pop-ing up. It happens even on a new sandbox instance.


This issue seems to be a classic recurring theme for everyone. So, I would share it here as a “reminder” for myself as well.

First, as an admin, navigate to Settings > Administration > Privacy Preference 


And select either to automatically send the error report or never send


Extra Info

If you would like to see what is going to be sent to Microsoft (in case there is a legitimate error). Click the “view the data that will be sent to Microsoft” to see the real error.


So far, I’ve seen very few informative log there. But it has saved me once or twice in troubleshooting real issues.




What matters with the Dynamics 365 v9.0

A quick disclaimer: this article is based on the preview program where the actual might differs.

Last week, I spent some more time watching again the recording of the Executive Briefing for Dynamics 365 July 2017 Preview Program. There is a massive load of good content and updates to Dynamics 365 in this next release. Traditionally, the preview program is under NDA and things that mentioned there are not for public consumption. However, a shift has happened in the direction of the preview program, where the information available there is no longer under NDA. A fellow MVP, Jukka Niiranen, posted a really good summary of this information on his blog:

After spending a few hours digesting again the recording, I would like to share a few key things that I’ve learned and thought as the outcome of the Executive Briefing as well as from documentations that are currently available.

An Exciting UI Revamp


The Unified Client that was mentioned during the Executive Briefing addressed quite significant issues of usability of the system. Reduction of white spaces, better tab navigation, text not to be wrapped anymore is a good sign for the usability. With this change, we all hope that users adoption would become much better. Now, when we are talking about user adoption, Dynamics 365 customers might need to start considering and thinking the plan for the change management. From my perspective, the more preparation of the change is the better user adoption will be.

Business EditionGuided Setup For Business.jpg

During the Executive Briefing, it was mentioned that the Business Edition (BE) will start with Sales & Marketing module and other capabilities will follow. The setup experience with the Business Edition seems to be simplified that much for the admin to setup, which is positive in a way. However, since it’s a new thing, everyone needs to learn it.

Simplified Settings.jpg

A few things that I noticed, would be as usual on what can/cannot be done in Business Edition. This screenshot from the presentation slide outlines the high-level limitation on Business Edition when it’s compared with the Enterprise Edition.

Business Limitation.jpg

And as per the first release, based on the question during the briefing, it seems there is no downgrade path for Enterprise Edition to Business Edition, at least for now.

No Downgrade.jpg

However, it seems to be possible to run Business and Enterprise edition in the same environment (still TBC though..)


And with the Business Edition, the configuration experience will also be different


My quick takeaway from the Business Edition: Be prepared to learn something (completely) new!

Platform Changes, Shift of Paradigm

With these exciting updates to the platform. Designing a Dynamics 365 solution is now no longer silo-ed within the Dynamics 365. Noticed that Microsoft Flow and Azure Logic Apps are becoming an integral part of Dynamics 365 solution. More and more integration and solutions will leverage this “native” capabilities (also become a space for us, Dynamics 365/CRM professional to start investing our time to learn).


With the Webhook supports, it opens up greater possibilities for Event-Driven processes/integration. This will work nicely with Azure function or any other APIs that support Webhook.


And Virtual Entity (this could be the end of data replication mindset)


Deprecation Announcements

With the release of v9.0, there are some components that are made deprecated.

  • Outlook Client
  • Service scheduling in Dynamics 365 for Customer Service
  • Dialogs
  • Parature knowledge base as the Dynamics 365
  • Project Service Finder app
  • Contracts, Contract Line Items, and Contract Templates
  • Standard SLAs
  • Relationship Roles
  • Mail Merge
  • Announcements
  • Silverlight (XAP) web resource

For more detail, have a read on Microsoft’s official documentation on this:

The deprecation announcement is important for us to start planning on how to handle the deprecation and move on with the latest available feature and start adopting the new feature for new implementations. The interesting ones are around Outlook Client, Dialogs, Contract-related entities and SLA. I believe this will require more planning.

For example, rolling out the new Outlook App might have some infrastructure/desktop rollout impact, as the current Outlook App has some compatibility gap with older version Exchange Server and Desktop Outlook (ref: Office 365 definitely solves the upgrade/infrastructure compatibility issue (another compelling reason where organisations should start considering moving to the cloud ;)).

Currently, Dialogs are there as the only way to prompt users for a value that can be consumed by the processes/workflow. Without any equivalent replacement, this could be a tricky situation. Some organisations might still using the contract-related and older SLA, and they work fine. If it becomes deprecated, then a change to the system is required.

Changes for Developers

Within the same documentation above, there is a section on “Some client APIs are deprecated” and I noticed the popular Xrm.Page library is now deprecated. This is in-line to support the new Unified Client structure. This means a really good planning needs to happen to be prepared with this release and start learning the new Client API/library.

For more details, there is another documentation from Microsoft for developers:


Dynamics 365 v9.0 is indeed a major upgrade, not only from the versioning, but also with the content. We all need to be ready to learn A LOT of new things and start embracing the latest and the greatest of the features to stay supported and ready for “undeniably” rapid changes to the platform. At this moment, we are just scratching the surface of the Dynamics 365 v9.0, I believe there are more to be unveiled and really excited about it!

Last but not least, even though the “briefing” for the upcoming preview program has completed, nothing is too late. Please feel free to sign up at

Microsoft Teams: Tips to Change Date/Time Format

We, at Barhead has just started our Microsoft Teams journey earlier this month. One thing that we noticed is that by default of standard installation every date/time formatting are in US format. Below is a sample of conversation log between me and my colleague. The conversation was happening a few weeks ago, which is still in the month of April, but the one showing below seems to be reverse of Australian time format (dd/MM/yyyy) and showing US format (MM/dd/yyyy).

Chat Log

So, I found out the way to change the date time format is by changing the Language. To change the language: Click on the “profile” icon at the bottom left of the application, and click on Language:


This then will open the selection of the language. Select your language. Note: in this window, Microsoft Team also specify that language will determine the date and time format.


Click Save and Restart to see the changes being applied!



Tips to Prepare for the Dynamics 365 exam – MB2-717: Sales


Today, I passed the Microsoft Dynamics 365 for Sales exam (MB2-717). So, I just would like to share the preparation tips that I’ve done to get this certification nailed down. I came from technical background, so this exam is slightly tougher for me to prepare 🙂

Note: As usual, you will not find any question that related to the exam here and I won’t give you any of it. NDA! NDA! NDA!

Skills Measured

Before starting to prepare for the exam, always review the Skills Measured section from the exam link:

Below is the extract of the topics/measurements based on the official page:

Create a Customer Organizational Structure (20% – 25%)

  • Manage customer records
    • Create and maintain a current customer base organizational structure; identify potential sales opportunities by utilizing core records such as accounts, contacts and customers
  • Manage the sales process
    • Create and maintain sales transactional records; track the sales progression; manage the sales process from lead generation through quote, order, and invoice creation
  • Manage customer communication
    • Create and manage social engagement sources, identify opportunities and generate leads
  • Manage sales literature and competitors
    • Create and maintain a sales literature repository, create an organized methodology for identifying and tracking competitors

Manage Leads and Opportunities (15% – 20%)

  • Manage leads
    • Identify leads and track them throughout the conversion process, reactivate or delete disqualified leads
  • Identify and manage opportunities
    • Identify opportunities to track throughout the sales workflow, create opportunities with a defined status, create records within the opportunity form, assign opportunities to designated sales staff
  • Utilize opportunity functionality
    • Close and document opportunities as won or lost, use Quick Create to add new information, connect opportunities to other record types, apply connections to a data structure
  • Manage opportunity relationships
    • Analyze lost sales opportunities through resolution activities, utilize multiple opportunity views

Manage Relationship and Sales Analysis (10% – 15%)

  • Manage relationship intelligence
    • Provision and configure Relationship Insights to integrate with Exchange, create and prioritize actions and tasks, track interactions, manage sales communication
  • Manage relationship analysis
    • Provision and configure relationship intelligence, create actionable and productivity cards by using Relationship Assistant
  • Integrate email with Dynamics 365 Sales
    • Track interactions with a specific email; manage sales relationships through statistical analysis of email activity, untracked emails and performance activities; manage sales relationships with Email Engagement; use engagement analytics and Auto-capture
  • Manage sales by using sales analysis tools
    • Improve sales tracking by using Advanced Find, editable grids and built-in reports; export data to Excel in both static and dynamic processes; export Excel templates

Manage the Sale Process (10% – 15%)

  • Manage the business process flow
    • Manage the tasks required of each state in the Business Process Flow, create territories and assign them to managers and sales staff, configure currency and exchange rates
  • Manage Products by using the Product Catalog
    • Manage prices lists, discount lists and unit groups; create, maintain and clone products; manage the product lifecycle
  • Manage price structures
    • Create price lists, create discount list models, assign currencies to products
  • Manage product relationships
    • Identify product relationships, differentiate product relationships by family units, customize properties for all products, identify and bundle related products
  • Manage sales transactional records
    • Create price and revenue structures with inclusion of line items, currency rates, exchange rates, and write-in products; manage the quote lifecycle; create and manage quotes, orders, and invoices

Improve Sales Performance (10% – 15%)

  • Manage goals
    • Create manageable and measurable goals, delineate goals by fiscal periods, specify definitions and goal metric records, analyze individual and organizational progress by creating goal hierarchies, use rollup queries
  • Manage visual tools with Sales Analysis
    • Create documents and templates, integrate charts and dashboards

Manage Customer Information (15% – 20%)

  • Operate Dynamics 365 sales functions
    • Identify and define the functional areas of Dynamics 365 Sales, model relationships and records in Microsoft Dynamics 365, access Dynamics 365 Sales through various client access methods, utilize the help center
  • Perform data management
    • Create customers and contacts within 365 Sales, enforce customer relationship by using activity types, use views and global searches
  • Perform lifecycle management
    • Utilize leads, convert leads into customers in the lead life cycle, perform opportunity management, manage cases

Now, below are the sources that I used to prepare for the exam.

Source #1: Dynamics Learning Portal

DLP always been my go-to source to prepare for Dynamics 365/CRM exam. So, for Sales exam, run through these courses:

Source #2: Revision Notes

Again, Neil Parkhurst has provided a good exam revision on Dynamics CRM 2016, the contents here are great. Since the core concepts for Sales has not been changed that much, this article is really recommended!

Source #3: Hands-On

As usual, to prepare for an exam, some hands-on experience is a must.

Try out the Sales-related scenarios, such as Lead qualifications, Opportunity management, Quote, Order, Invoice, Goal, Metric, Rollup Query. Get the understanding of the options to do data analysis: View, Report, Excel, Dashboard, Chart and Power BI.

One thing that I noticed quite interesting for the Skills Measured here for the Sales exam is around the Relationship Insight. At this moment, this feature is only available in Preview for North America region. This is a bit hard for us that are based on the other regions to have hands-on experience.

To prepare on the Relationship Insight topic, Microsoft Dynamics team posted a great blog on this instance

Below are the curated links from the above blog post and try to get the understanding of what features do what would be helpful as the preparation for the exam:


Melbourne Dynamics 365 User Group YouTube Channel

Melbourne Dynamics 365 User Group - YouTube Channel

After a few weeks of planning, from the UG Committee, we are pleased to have our Melbourne Dynamics 365 User Group YouTube channel up and running. Special thanks to Sahan Wijayasekera who recorded and provided the equipment during the day!

Our YouTube channel will consist of the recording of the UG sessions and we hope this channel can be helpful for the wider audience and/or for those that missed the session due to other commitments.

Below is the link to the YouTube channel, please enjoy and subscribe 🙂

Regardless of the recording, it’s still the best way to get the fresh presentation, chance to ask the questions to the presenters or other experts, as well as the networking opportunity by attending the UG yourself. So, please sign up and RSVP on our Meetup site for the next session:


Tips to prepare for the Dynamics 365 exam – MB2-716: Customization and Configuration

Recently I passed the Microsoft Dynamics 365 exam on Customization & Configuration (MB2-716). I just would like to share the preparation tips that I’ve done to get this certification nailed down.

Note: You will not find any question that related to the exam here and I won’t give you any of it, as it is part of the NDA.

Source #1: Dynamics Learning Portal

This exam is considerably new (released 1-2 months ago). When I was preparing for the exam, the only official material that is available is from Dynamics Learning Portal:

If you have worked with the previous version(s) of Dynamics 365/CRM, these DLP courses can be used to refresh most of the concept of the subject. But for the newcomers, these learning modules are really recommended!

Source #2: Revision Notes

Another source that is really helpful to help me passing this exam is Neil Parkhurst’s revision notes: The content is for Dynamics CRM 2016. However, 80-90% of the content is still applicable for Dynamics 365.

Source #3: Hands on Experience

 Mistakes are the best lessons ,   While experience is the best teacher

Image taken from:

As the wise man says “Experience is the best teacher”, hands-on experience with the system is a must!


So, without breaching the NDA, below are the topics (not exhaustive and I’m not covering all topics here) that I hope would help you to prepare for the exam:


Managing Dynamics 365 Online Encryption Key

Today, when I navigate to edit one of the Dynamics 365 Online instances, I just noticed a new section that is available on my trial instance: “database encryption settings”


So, what can you do with this shiny new feature?

Based on the official documentation for this feature from Microsoft:

The manage keys feature lets you perform the following tasks.

  • Enable the ability to self-manage database encryption keys that are associated with Dynamics 365 (online) instances.
  • Generate new encryption keys or upload existing .PFX or .BYOK encryption key files.
  • Lock a Dynamics 365 (online) instance.
    You should never lock an instance as part of your normal business process. While a Dynamics 365 (online) instance is locked it takes the instance completely offline and it cannot be accessed by anyone, including Microsoft. Additionally, services such as synchronization and maintenance are all stopped. An appropriate reason why you would lock an instance is when you move your database from online to on-premises. Locking the instance can make sure that your online data is never accessed again by anyone.

    A locked instance can’t be restored from backup.

  • Unlock a Dynamics 365 (online) instance. To unlock a locked instance of Dynamics 365 (online), you must upload the encryption key that was used to lock it. While a Dynamics 365 (online) instance is locked, it cannot be accessed by anyone.


One of the common request when I’m implementing Dynamics 365 (CRM) deployment, is the question around the security & encryption. One of the common ask is whether the platform allows customer-supplied encryption key or not? In the past, my answer is NO. It is all under Microsoft’s managed encryption key.

With this feature being made available, the answer is YES!


Read through the TechNet article above for more details of this new feature and considerations when you are implementing this BYOK 🙂


Dynamics 365 PSA – I can’t see WBS? What’s wrong with my security role?

This is another finding from deploying Dynamics 365 PSA. So, during the testing phase, I noticed the test user account could not see WBS link under project entity.

The copied security role assigned to the test user has complete (Create, Read, Write, Delete, Append, Append To, Share and Assign) to Project and Project Task entity. The security role was copied from Sales Person as the role is more specific for sales scenario.

Upon investigation, apparently for this role to be able to see the WBS is to add ISV Extensions privilege



Lesson Learned from PSA Deployment

Currently I’m in a project where our team is going to roll out Dynamics 365 Project Service Automation for one of our customers. Throughout the project, we’ve learned a lot about this new cool kid on the block 🙂


Some gotchas/lesson learned when we are rolling out this to the customer:

  1. Choose Project Template carefully. Once created, the user can’t change the project template and need do it again from the scratch (not a big hassle, but definitely I mentioned this when during the training).

  2. This is for Admin/Customizer, PSA-related controls limitation. Time Entry & Expense, WBS, schedule board, etc. They are pretty much static (hard coded), it is not honoring relabel, adding more options and even can’t add any new field. Seems like we need to treat PSA in a similar manner to other ISV solution, such as Click Dimensions, (compared to Sales/Service/Marketing that have more mature customization and configuration flexibility).

  3. Do not mess with the OOTB processes or scripts. There are lots of processes coded in javascripts and plugins where the processes behind it are not really documented. So, my lesson on it, keep it out of the box, if a customization needed, I would recommend to not touching any of the OOTB fields and create custom processes or fields instead.

  4. Pay attention to “metadata” records (Resource Role, Resource Skill, Price List, Expense Categories, etc) during deployment. Similar to Adx/portal scenario, where records are stored as configuration. To have ALM for PSA correctly, will need to pay attention to those records as part of the deployment process.

  5. One of the biggest catch that I’ve got: can’t undo approval. Approvers need to be really really careful with their approval.

For this instance, I submitted an idea entry: From the feedback from the 2 customers that we have worked with, they need this feature to make an amendment to the entries, at least before it is processed for invoice (at least a flag or something to cater this scenario).

  1. Data migration is a bit tricky, for some scenarios, we’ve got to deactivate some of the validation plugins to let the data in (need to have thorough testing on this, as I consider this as touching the OOTB process that is not well documented).

Hope this helps!

iOS Outlook Add-ins is now available!

Last week I posted my gotcha around Dynamics 365 Outlook App. This weekend I noticed a notification on my phone to update the Outlook app to the latest version.

What surprises me is the availability of the long waiting add-ins feature that has been demoed in the Dynamics 365 launching. The following article mentioned about the Dynamics 365 add-ins:

So, I wait for no further to update it straight away and viola! I can now get my Outlook add-ins available on my Outlook app on my phone!


There is a functionality to open the record. Since I have Dynamics 365 mobile app installed as well, the Outlook app is opening the record detail in the Dynamics 365 mobile app.


Gotchas on Dynamics 365 Outlook App Deployment

Microsoft Dynamics 365 has a shiny new Outlook App. In this post, I won’t discuss the functionality of this Outlook App (for the information about functionality, please use the following article:

One of the first pre-requisite of the new Dynamics 365 Outlook App is to enable the server-side sync ( Once the server-side sync for the user’s mailbox completed, the user will be displayed under Dynamics 365 App for Outlook as Eligible User:

Add Outlook App.png

Click the “ADD APP TO OUTLOOK” button to let the provisioning service adding the Outlook App. This might take up to 15 minutes to finish the provisioning. For more information about the security requirements, supportability, compatibility and more details of the deployment, please refer to the following TechNet article:

Once you’ve got it provisioned, it will be available on your desktop-based Outlook:

Outlook App.png

As well as on OWA client: OWA.png


Gotcha #1 – Outlook App Doesn’t Like Multiple Dynamics 365 Instances

Now, as I’m happy with the App, I would like to make it available in other Dynamics 365 instances (Typical IT project lifecycle we will have multiple environments to be used for their purpose, such as: DEV/TEST/UAT/PROD).

So, what I have done was made the same configuration at the other environment, let say in UAT environment. And add progressing to add the app to Outlook. However, I’ve got the following error:


“Issue when adding to Outlook” – with detail: “CRM : IncomingEmailRejected”.

So I click the link “Help me resolve this issue” that takes me to the following KB Article:

The article mentioned the cause of the problem: “This error can occur if the Mailbox record has not been approved.”

Well, I’ve approved the mailbox. Otherwise, how come I could get a success message from the testing result:


To resolve this issue. I need to update the Mailbox synchronisation to the current organisation only. Which means, I can only sync and use the Outlook App for an instance at a time (which makes sense).


Once I ticked this option, I can add the Outlook App successfully for the new instance.

So, the feature of the traditional Outlook Client that is able to keep the configuration of multiple instances and switching on which one that becomes the syncing org, seems to be not available for the Outlook App.


Gotcha #2 – How to Remove or Disable the Dynamics 365 Outlook App?

Now, in some situations, it could be a business decision whether they would like to use the new Dynamics 365 Outlook App or the Traditional Outlook client. One thing that I noticed, once I enabled the Dynamics 365 Outlook App for the user, I can’t find anywhere in CRM UI to remove it:

Nowhere to remove.png

It can only add, but not remove… Okay, this is not the end of the world. The Dynamics 365 Outlook App is technically an “Add-in” for Outlook. So, to remove it, simply navigate to File > Info > Manage Add-ins from Outlook desktop.

Manage Add-ins.png

That practically will redirect you to Outlook OWA:

Manage Add-ins OWA.png

Now in here, we can see the list of Outlook add-ins that have been installed for us. Click Dynamics 365, in there we also can see which Dynamics 365 instance that the App is currently connected to.

To disable: simply untick “Turned on” checkbox.

To remove: select the add-ins and click the minus (-) button.


For now, these are the lessons learned that I’ve got from the Dynamics 365 App.


Editing Sitemap in Dynamics 365

Prior to the release of Dynamics 365, we are helped a lot by XrmToolbox to edit the sitemap without the need of editing the sitemap XML manually. However, with the release of Dynamics 365, it seems the plugin for XrmToolbox doesn’t support the editing of Dynamics 365 sitemap (given now it is possible for a Dynamics 365 deployment to have multiple Apps and each App can have their own sitemap).


So, what should we do now? There are 2 options to configure the Sitemap in Dynamics 365.

Option #1: Creating a new App

With the ability to create App in Dynamics 365, we can create a sitemap that is associated to the App. Following the guide from Microsoft on how to configure/design the app:

Option #2: Editing the Default Sitemap

Editing default sitemap is similar to what we used to do with XrmToolbox. However, with the unavailability of XrmToolbox to achieve this, we need to use the Dynamics 365 Sitemap Editor to do this.

How to get there? Here are the steps to update the Default Sitemap:

  1. Open the Solution that you would like to use to contain the sitemap.
  2. Under Components. Select Client Extensions > Add Existing > Select “Site Map”Sitemap.png
  3. Once it’s added to the solution, click on the Edit buttonEdit.png
  4. It will then open up the Dynamics 365 Sitemap Editor. Conceptually it’s the same as the way we configure Sitemap using the XrmToolbox, but with different user experience and layout.D365Sitemapeditor.png
  5. Once you are happy with the layout, click Save and then Publish.


Extra Tips: Change the Default “Dynamics 365 – custom” App name

By default, each Dynamics 365 instance will get a default App. To change this App name:

  1. Navigate to Settings > Administration > System Settings
  2. Under “General” tab scroll down to the last optionsDefaultAppName.png



Dynamics 365 (On-Premises) Is Released

It seems the wait is over for CRM On-Premise customers to get the latest update of Dynamics 365 (Re-branding seems to cause confusions to some of us).

Download link:

This version is 8.2, which is the same base version to the current version on the cloud version. The following components are now available for download:


Note the filename is still using “CRM2016”. As a rule of thumb in avoiding confusion, please refer to the version number 🙂

Looking forward to upgrade one of my VMs in Christmas break!

When Case Routing is not Working, Check the Team Security Role

Recently I worked on a demo to showcase Dynamics 365 Service (case management) capability. One of the feature that I would like to show is the case routing functionality.

I’ve created a simple rule, let say IF the case type = product enquiry, assign the owner to Product team.

So, I tried the rule by clicking save & route button on the case form, but it doesn’t do what I expect it to do…


Later I found out that the team that the case routing rule has been configured with, doesn’t have enough privilege to own a case (in my case this was a brand new team, without security role assigned).

After I assigned the appropriate security role, now the routing works as expected.

I hope this help anyone who might encounter the same issue.

Note: I’ve submitted an idea (link below) to allow preemptive message to let us know if the rule doesn’t have enough privilege. Please vote it up if you think this will be helpful. 


CRM Chat Bot: Part 4 – Deployment & Action!

In the previous part of this series, we have seen the sample implementation and how the code is running against a CRM Online instance. In this post I will show on how to deploy the chat bot to the supported channels.


As illustrated above, the built bot has the capability to be deployed to multiple channels leveraging the built-in capability of Bot Connector library.

Bot Registration

To deploy the bot, first we need to sign up to register the bot: (this requires a Windows Live ID to sign up). Once signed-up, you will be able to register the new Bot:


You will then be asked to setup the App ID and password. Please take note of this App ID and password, as this will be the one that we will use in the Web.Config.


Then update your web.config of the bot with the generated App Id and Password.


Now we are ready to deploy to Azure App Service. You need to make sure that your Visual Studio has the latest Azure SDK. To publish it, right click the bot project and click on Publish.


This will prompt the details for the Azure App Service deployment.BotAppService1.png

Continue to create, once the App Service has been created, it will show below screen:


Note: Take note the destination URL, this will be the bot endpoint. You will need this base URL  and  the API path”/api/messages” to be configured on the bot registration site.


Once the endpoint has been setup properly, you could verify and test the connectivity:


Channels Configuration

Congratulations, we are nearly there. The next step is to configure the channels. Skype and Web Chat are automatically configured by default. To add other channel it is really simple. Just follow the guide provided by Microsoft is sufficient.


Once it’s configured with the details, now here is the bot in action:


As I’ve configured it on different channels, the same Bot is working on different platforms, such as Slack and Skype.

Example on Slack:


Example on Skype:



Microsoft Bot Framework is relatively new for the community, however it has produced a great framework to built multi-channels conversational bot. Where the developers only need to developed the bot once and it can be deployed in many different channels rapidly.


The diagram above depicts the high level on how the bot application is deployed and work together as a solution.

I hope this post helps you to gain the understanding on the Bot Framework and how it can be integrated with Dynamics CRM and other Microsoft platforms.

This post is the end of the CRM Chat Bot series. There will be a spin-off post on a topic related to Luis Model that was used in this example. So, stay tuned 🙂



CRM Chat Bot: Part 3 – Development Deep Dive + Integration To Dynamics CRM

In the part 2 of the series, we have discussed on the concept of how the Bot Framework library is used to assist us building conversational bot. As promised in the previous post, I’m going to share the source code on how the bot framework can be integrated with Dynamics CRM.

The Story

Now, to build a conversational bot, it will begin with the use case of the bot. In my example, I’m going to use an imaginary  car dealer with this simple “User Story” from Scrum principle: “As a customer, I want to be able chat and let the company know that I want to test drive a car, so that I can make an informed decision when I’m buying the car”.

The Implementation

In the previous post, we have discussed the concept of Dialog, Form Flow and Luis Dialog. Now in this post, I will show on how these concept can be applied.

In general I’m creating the TestDriveDetail class to contain the test drive request detail:

namespace CrmChatBot.Model
public class TestDriveDetail
public string CarMake { get; set; }
public string CarModel { get; set; }
public string RequestedTime { get; set; }
public string CustomerName { get; set; }
public string PhoneNumber { get; set; }

Notice that all classes that will be used in Bot Framework will need to be decorated with [Serializable].

And a simple helper class to create the record to CRM.

public static void CreateTestDrive(TestDriveDetail testDrive, IOrganizationService crmService)
var lead = new Microsoft.Xrm.Sdk.Entity(EntityName);
lead.Attributes.Add(Field_Subject, $"Test Drive Request by {testDrive.CustomerName}");
lead.Attributes.Add(Field_FirstName, testDrive.CustomerName);
lead.Attributes.Add(Field_Description, $@"Test drive request summary:
{Environment.NewLine}Car Make: {testDrive.CarMake},
{Environment.NewLine}Car Model: {testDrive.CarModel},
{Environment.NewLine}Requested Time: {testDrive.RequestedTime},
{Environment.NewLine}Customer Name: {testDrive.CustomerName},
{Environment.NewLine}Phone Number: {testDrive.PhoneNumber}");

Now, I’ll give the example of the simple implementation with the 3 different techniques (Dialog, Form Flow and Luis Dialog).

Sample #1: Simple Dialog


The sample dialog is a series of prompt and at the end of the process it the store the information in CRM Online. Below is sample code of the Dialog, how the chain of prompts are created and at the end it is storing the record in CRM.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using System.Text.RegularExpressions;
using CrmChatBot.Model;
using CrmChatBot.CRM;
namespace CrmChatBot.Dialogs
public class CarInquiryDialog :IDialog<object>
protected TestDriveDetail testDriveDetail;
public async Task StartAsync(IDialogContext context)
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
var message = await argument;
if (message.Text.Contains("test drive"))
testDriveDetail = new TestDriveDetail();
context: context,
resume: CarMakeHandler,
prompt: "What car make do you want to test?",
retry: "Sorry, I don't understand that."
else if (message.Text == "No")
await context.PostAsync("Hi there, anything that I can help for you today?");
public virtual async Task CarMakeHandler(IDialogContext context, IAwaitable<string> argument)
var carMake = await argument;
testDriveDetail.CarMake = carMake;
context: context,
resume: CarModelHandler,
prompt: "What car model do you want to test?",
retry: "Sorry, I don't understand that."
public async Task CarModelHandler(IDialogContext context, IAwaitable<string> argument)
var carModel = await argument;
testDriveDetail.CarModel = carModel;
context: context,
resume: PreferredTimeHandler,
prompt: "When would you like to come for test drive?",
retry: "Sorry, I don't understand that."
public async Task PreferredTimeHandler(IDialogContext context, IAwaitable<string> argument)
var prefTime = await argument;
testDriveDetail.RequestedTime = prefTime;
context: context,
resume: CustomerNameHandler,
prompt: "Your name please?",
retry: "Sorry, I don't understand that."
public async Task CustomerNameHandler(IDialogContext context, IAwaitable<string> argument)
var customerName = await argument;
testDriveDetail.CustomerName = customerName;
context: context,
resume: ContactNumberHandler,
prompt: "What is the best number to contact you?",
retry: "Sorry, I don't understand that."
public async Task ContactNumberHandler(IDialogContext context, IAwaitable<string> argument)
var contactNumber = await argument;
testDriveDetail.PhoneNumber = contactNumber;
await context.PostAsync($@"Thank you for your interest, your request has been logged. Our sales team will get back to you shortly.
{Environment.NewLine}Your test drive request summary:
{Environment.NewLine}Car Make: {testDriveDetail.CarMake},
{Environment.NewLine}Car Model: {testDriveDetail.CarModel},
{Environment.NewLine}Requested Time: {testDriveDetail.RequestedTime},
{Environment.NewLine}Customer Name: {testDriveDetail.CustomerName},
{Environment.NewLine}Phone Number: {testDriveDetail.PhoneNumber}");
//CrmLead.CreateTestDrive(testDriveDetail, CrmDataConnection.GetAPI());
CrmLead.CreateTestDrive(testDriveDetail, CrmDataConnection.GetOrgService());
context.Done<string>("Test drive has been logged");

Sample #2: Form Flow


As you can see at the above screen, the form flow is automatically generate the questions with the pre-defined options. Below is the source code of Form Flow implementation:

using CrmChatBot.CRM;
using CrmChatBot.Model;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CrmChatBot.FormFlow
public enum CarMakeOptions { Unknown, Honda, Toyota };
public enum CarModelOptions { Unknown, Jazz, City, CRV, Accord, HRV, Yaris, Corolla, Camry };
public class CarInquiryFormFlow
public CarMakeOptions CarMake;
public CarModelOptions CarModel;
public string PreferredTime;
public string Name;
public string ContactNumber;
public static IForm<CarInquiryFormFlow> BuildForm()
OnCompletionAsyncDelegate<CarInquiryFormFlow> processRequest = async (context, state) =>
await context.PostAsync($@"Your test drive request summary:
{Environment.NewLine}Car Make: {state.CarMake.ToString()},
{Environment.NewLine}Car Model: {state.CarModel.ToString()},
{Environment.NewLine}Requested Time: {state.PreferredTime},
{Environment.NewLine}Customer Name: {state.Name},
{Environment.NewLine}Phone Number: {state.ContactNumber}");
var testDriveDetail = new TestDriveDetail
CarMake = state.CarMake.ToString(),
CarModel = state.CarModel.ToString(),
RequestedTime = state.PreferredTime,
CustomerName = state.Name,
PhoneNumber = state.ContactNumber
// save the data to CRM
CrmLead.CreateTestDrive(testDriveDetail, CrmDataConnection.GetOrgService());
return new FormBuilder<CarInquiryFormFlow>()
.Message("Welcome to the car test drive bot!")
.Message("Thank you for your interest, your request has been logged. Our sales team will get back to you shortly.")

To initiate the Form Flow from message controller:

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
if (activity.Type == ActivityTypes.Message)
// Initiates the form flow
await Conversation.SendAsync(activity, MakeRootDialog);
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
internal static IDialog<CarInquiryFormFlow> MakeRootDialog()
return Chain.From(() => FormDialog.FromForm(CarInquiryFormFlow.BuildForm));

view raw


hosted with ❤ by GitHub

Sample #3: Luis Dialog

Now, we have seen how Dialog and Form Flow is getting the simple conversation started. However, if you might notice, the bot can only understand predefined keywords or options. (In Dialog, it is hard-coded to find “Test Drive” and in FormFlow it is directly asking the detail).

To overcome this, Microsoft has come up with a really cool Language Understanding Intelligent Service, a.k.a LUIS. In this post, I’m not going to describe in detail on how to setup LUIS model (will do next time), but I would like to introducing its capability that is able to predict/interpret the intent of the user. For this sample, I’ve prepared the following LUIS model:


This model is configured to be able to interpret the intent of the user (Greeting, Test Drive, Ending Conversation, Brochure Request, None).


Now, below is the source code on how the Luis Dialog is built.

using CrmChatBot.CRM;
using CrmChatBot.Model;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace CrmChatBot.LUIS
[LuisModel("LuisAppId", "LUIS Subscription Key")]
public class CarInquiryLuisDialog : LuisDialog<object>
protected TestDriveDetail testDriveDetail;
public const string Entity_Car_Make = "CarMake";
public const string Entity_Car_Model = "CarModel";
public const string Entity_Date = "";
private EntityRecommendation carMake;
private EntityRecommendation carModel;
private EntityRecommendation preferredDate;
public async Task None(IDialogContext context, LuisResult result)
string message = $"Sorry I did not understand: " + string.Join(", ", result.Intents.Select(i => i.Intent));
await context.PostAsync(message);
public async Task Greeting(IDialogContext context, LuisResult result)
string message = $"Hi, is there anything that I could help you today?";
await context.PostAsync(message);
[LuisIntent("Ending Conversation")]
public async Task Ending(IDialogContext context, LuisResult result)
string message = $"Thanks for using Car Inquiry Bot. Hope you have a great day!";
await context.PostAsync(message);
[LuisIntent("Test Drive")]
public async Task TestDrive(IDialogContext context, LuisResult result)
testDriveDetail = new TestDriveDetail();
context: context,
resume: CarMakeHandler,
prompt: "What car make do you want to test?",
retry: "Sorry, I don't understand that."
[LuisIntent("Brochure Request")]
public async Task BrocureRequest(IDialogContext context, LuisResult result)
testDriveDetail = new TestDriveDetail();
context: context,
resume: BrochureRequestHandler,
prompt: "Which car do you want to get the brochure information?",
retry: "Sorry, I don't understand that."
#region Brochure Request Handler
public virtual async Task BrochureRequestHandler(IDialogContext context, IAwaitable<string> argument)
var car = await argument;
await context.PostAsync($"We have received your brochure request for {car}. Our sales team will send it out to you.");
context: context,
resume: AnythingElseHandler,
prompt: "Is there anything else that I could help?",
retry: "Sorry, I don't understand that."
#region Test Drive Prompt
public virtual async Task CarMakeHandler(IDialogContext context, IAwaitable<string> argument)
var carMake = await argument;
testDriveDetail.CarMake = carMake;
context: context,
resume: CarModelHandler,
prompt: "What car model do you want to test?",
retry: "Sorry, I don't understand that."
public async Task CarModelHandler(IDialogContext context, IAwaitable<string> argument)
var carModel = await argument;
testDriveDetail.CarModel = carModel;
context: context,
resume: PreferredTimeHandler,
prompt: "When would you like to come for test drive?",
retry: "Sorry, I don't understand that."
public async Task PreferredTimeHandler(IDialogContext context, IAwaitable<string> argument)
var prefTime = await argument;
testDriveDetail.RequestedTime = prefTime;
context: context,
resume: CustomerNameHandler,
prompt: "Your name please?",
retry: "Sorry, I don't understand that."
public async Task CustomerNameHandler(IDialogContext context, IAwaitable<string> argument)
var customerName = await argument;
testDriveDetail.CustomerName = customerName;
context: context,
resume: ContactNumberHandler,
prompt: "What is the best number to contact you?",
retry: "Sorry, I don't understand that."
public async Task ContactNumberHandler(IDialogContext context, IAwaitable<string> argument)
var contactNumber = await argument;
testDriveDetail.PhoneNumber = contactNumber;
await context.PostAsync($@"Thank you for your interest, your request has been logged. Our sales team will get back to you shortly.
{Environment.NewLine}Your test drive request summary:
{Environment.NewLine}Car Make: {testDriveDetail.CarMake},
{Environment.NewLine}Car Model: {testDriveDetail.CarModel},
{Environment.NewLine}Requested Time: {testDriveDetail.RequestedTime},
{Environment.NewLine}Customer Name: {testDriveDetail.CustomerName},
{Environment.NewLine}Phone Number: {testDriveDetail.PhoneNumber}");
//CrmLead.CreateTestDrive(testDriveDetail, CrmDataConnection.GetAPI());
CrmLead.CreateTestDrive(testDriveDetail, CrmDataConnection.GetOrgService());
context: context,
resume: AnythingElseHandler,
prompt: "Is there anything else that I could help?",
retry: "Sorry, I don't understand that."
public async Task AnythingElseHandler(IDialogContext context, IAwaitable<bool> argument)
var answer = await argument;
if (answer)
await GeneralGreeting(context, null);
string message = $"Thanks for using Car Inquiry Bot. Hope you have a great day!";
await context.PostAsync(message);
context.Done<string>("conversation ended.");
public virtual async Task GeneralGreeting(IDialogContext context, IAwaitable<string> argument)
string message = $"Great! What else that can I help you?";
await context.PostAsync(message);

That’s all for the sample codes! I hope this helps. For the code repository, feel free to have a look at github repo:

Stay tuned for the next part of this series: Deployment.


CRM Chat Bot: Part 2 – Microsoft Bot Framework Development Concept

In the Part 1 of this series we have explored on how to configure the development environment and run the Bot Framework template to get the “Hello World” kind of reply from the Bot.

Now in this part, I would like to discuss about the development concept of Bot Framework. Behind the scene Bot Framework is an API that is encapsulated within Bot Connector library. The focus of the API itself is to provide a conversational context. Each conversation that come from the user is captured as “Activity”. “Activity” class is part of Bot Builder library. So, be careful not to mixed up with the other “Activity” class on Microsoft .Net framework or even from Dynamics CRM SDK. (Ref:

So far there are 6 activity types that the Bot Framework has:

ActivityType Interface Description
message IMessageActivity a simple communication between a user <-> bot
conversationUpdate IConversationUpdateActivity your bot was added to a conversation or other conversation metadata changed
contactRelationUpdate IContactRelationUpdateActivity The bot was added to or removed from a user’s contact list
typing ITypingActivity The user or bot on the other end of the conversation is typing
ping n/a an activity sent to test the security of a bot.
deleteUserData n/a A user has requested for the bot to delete any profile / user data


From the above activity types, “message” probably will be the most commonly used activity type.

Now, let’s drill down to the Activity class. The fundamental basic of Bot is to reply the message that is typed by the end user.

Now, let’s take a look at the code that is generated by the template to understand the basic of message reply from the Bot.


The highlighted part of the code above is the basic on how the Bot Framework is constructing the reply to the activity.

Ok, we might have the reply from the bot, but it is just the same reply all the time, it is not useful. Bot should be able to engage the user with something meaningful. So, to start a meaningful conversation there are some concepts that we can use: Dialog, FormFlow and Luis.

Note: In this post, I will cover just the high-level concept first and will deep dive with the code examples on the next post.

1.     Dialog

Dialog is the basic model of conversational process. Each Dialog in Bot Framework is encapsulated in a C# class that implements IDialog. The overview of Dialog provided by its documentation (

Dialogs model a conversational process, where the exchange of messages between bot and user is the primary channel for interaction with the outside world. Each dialog is an abstraction that encapsulates its own state in a C# class that implements IDialog. Dialogs can be composed with other dialogs to maximize reuse, and a dialog context maintains a stack of dialogs active in the conversation. A conversation composed of dialogs is portable across machines to make it possible to scale a bot implementation. This conversation state (the stack of active dialogs and each dialog’s state) is stored in the state service provided by the Bot Connector service, making the bot implementation stateless between requests. (Much like a web application that does not store session state in the web server’s memory.)

In short, Dialog is the simplest conversation building block for Bot to communicate/reply. Dialog can be meaningful with its Chain method. To make it simple analogy, Chain can be illustrated as a series of command prompt dialog that will handle the reply from the user.

2.        Form Flow

Dialog is good for a starter piece of conversation. However, it can be really tedious job to build the Dialog that might have some aspects of ambiguity. Form Flow, as the name suggests, is based on the idea of a form, where there is a collection of fields to be captured throughout the conversation. Form Flow share the same principle as Dialog, where a “Form” is built through a C# class. Where it is using basic C# data types, such as: Integral, Floating Point, String, DateTime, Enum and List of Enum.

3.        LUIS

Now, with Dialog and Form Flow, the bot can handle basic conversations, however the bot itself will only understand the command based on the pattern of the message. With LUIS (Language Understanding Intelligent Service) from Microsoft, the Bot can be smarter to predict what is the intent of the user. To use LUIS, in code, it will be similar to the normal Dialog class, but we will inherit LuisDialog instead of the IDialog class.

A comparison of normal Dialog vs LUIS Dialog is applicable when we need to handle a conversation that initiates a car interest. With the normal Dialog, we need to put some hard-coded If-Else conditions and regex patterns to predict what is the user wants. But with LUIS, it will provide an output of the possible intents based on the conversation reply analysis.

Part 2 – Conclusion

So, I hope this post helps you to get the basic understanding of Microsoft Bot Framework and get the understanding of the toolset that the SDK provides. Stay tuned for the Part 3 – Development Deep Dive + Integration Through CRM API.

CRM Chat Bot: Part 1 – Getting Started with Microsoft Bot Framework

Microsoft quite recently announced the Microsoft Bot Framework on Build Conference 2016. Below is the overview of the vision of Bot Framework from Microsoft:

The Microsoft Bot Framework provides everything you need to build and connect your bots to your users wherever they converse – from SMS to Office 365 mail to Slack and more… It’s your bot, wherever your users are talking. Learn how to use the Bot Framework to build a bot with your own existing code, use the Bot Builder to generate conversational dialogs from scratch, and more to give your bot skills with natural language processing and deep learning technology. Walk away with tools to build a great bot that can connect with users, wherever they are.

I’ve spent a few months reading and researching on the new Microsoft Bot Framework and I hope with this blog post series I could share and introduce how Microsoft Bot Framework to work together with Dynamics CRM.

Getting Started

Microsoft Bot Framework supports Node.js, .NET and REST Bot Builder SDK. In my posts, I will use .NET based bot, as this is the most common platform that CRM developers use to reduce the learning curve with the Bot Framework.

To start building the bot, we need to set the development environment. Below is my development environment setup:

  • Visual Studio 2015 Update 3 (latest update)
  • Bot Builder SDK (download links are here)
  • Visual Studio C# template (download here)
    • To install, extract the downloaded template and copy it to Visual Studio Project Template. Typically it is located on: “Documents\Visual Studio 2015\Templates\ProjectTemplates\Visual C#”
  • Bot Framework Emulator (download here)
  • Microsoft Account
  • Microsoft Azure subscription (trial license should do)

Once the environment has been configured, you should be able to see the new project template to be available in Visual Studio:


Let the Journey Begins…

Now let’s create a new bot application. This will give you the following project structure:


Then we need to install these NuGet packages:

If your environment setup is successfully installed, you would be able to see a page similar to below on build:


Bot Emulator

We will use the Bot Emulator to simulate the conversation. Take note of the URL of the page before and enter it in Bot URL.


You now will see that the bot is replying. Congratulations, you have your first reply from your bot 🙂 

Lesson Learned/Troubleshooting

  1. During the research, I encountered a few differences on the sample code. Some of them used “Message” and some have “Activity”. Apparently, it is part of the update on Bot Framework V3 ( that Microsoft changed the usage of Message to Activity.
  2. Another difference in Bot Framework V3 is that you no longer need Microsoft.Bot.Connector package, Microsoft.Bot.Builder is now include the Microsoft.Bot.Connector assemblies.
  3. Use .Net Framework 4.6 and above to develop Bot. I used 4.5.2 (as this is the current supported framework for Dynamics CRM), this will resulting the installation of Microsoft.Bot.Builder package to fail:

Install-Package : Could not install package ‘Microsoft.Bot.Builder 3.2.0’. You are trying to install this package into

a project that targets ‘.NETFramework,Version=v4.5.2’, but the package does not contain any assembly references or

content files that are compatible with that framework. For more information, contact the package author.

At line:1 char:1

+ Install-Package Microsoft.Bot.Builder

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception

    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand


Stay tuned for the Part 2: Microsoft Bot Framework Development Concept!

CRM Ideas, Let your ideas listened

Microsoft just announced CRM Ideas portal:

Previously the way we submit our feedback/ideas is through Microsoft Connect: However it seems this site might not be known well and the user experience on that site is not as good as the new portal.

The new portal seems to be based on AdxStudio, from the profile management perspective:idea_portal_profile.png

The user interface of the idea portal is also looks nicer compared to the previous portal:


So, what are you waiting for, submit your idea now!

Note: Before you post, please read this posting guideline:

Ribbon Workbench 2016 beta on XrmToolBox

I just recently re-opened my XrmToolBox to do some Sitemap modification and found out some new plugins are available on the XrmToolBox plugin store. One of it is Ribbon Workbench 2016 beta by Scott Durow.

My first test run on my solution showing that the 2016 version is much quicker compared to the Silverlight-based version that is running on CRM web app.


Looking forward for the final version. It will be awesome!


Gotcha Working with Dynamics CRM Web API: Grammar..

Microsoft has suggested developers to start using the new Web API to develop new custom development. As they are planning to deprecate the 2011 endpoints sometime after CRM version 9 (We are on version 8 now!). Ref:

So, I’ve embraced the Web API in my new projects for javascript codes. Typically I would use CRM Rest Builder by Jason Lattimer to build Web API request in Javascript.

I found out it is quite interesting on one of my custom entity, let’s call it “cust_selectionmatrix”. I tried to build the query using the tool, but I won’t generate the query as expected. Then I tried to look at Microsoft examples around the Web API query. Most of them are appending “s” against the entity name. E.g: for account: /api/data/v8.0/accountand for contact: /api/data/v8.0/contacts.

So my first trial is just adding s at the end of my custom entity: /api/data/v8.0/cust_selectionmatrixs. However, I’ve got a weird error:

"Resource not found for the segment 'cust_selectionmatrixs'."

Then after I tried to find the list of entity for Web API using  <CRM Server URL>/api/data/v8.0/I found out that my entity is named: “cust_selectionmatrixes” in the Web API. I reckon this is how CRM is implementing “English”. So, if your entity ends with: ‑s, ‑sh, ‑ch, ‑x, or ‑z. Just append ‘es‘ to your entity name to work with the Web API.



Then.. There was an awkward moment when I have an entity named “cust_settings” and it is translated as “cust_settingses“… 15jkjv.jpg

Dynamics CRM Online 2016 Update 1 is Up!

I just recently spun up a new trial instance for practice purpose and noticed a slight difference on the notification bar. Out of curiosity I checked the CRM version, and…


My new trial instance is running version 8.1!

Looking forward to test what has been announced previously:

Exciting times ahead!

CRM Online diagnostic with SaRA (Support and Recovery Assistant)

The CRM Support team recently released a new tool to diagnose Dynamics CRM Online connectivity issue. The initial CRM Online scenario is for CRM Outlook Client configuration issues.  This diagnostic can detect issues related to CRM Outlook Client install, configuration, and can also detect and fix a disabled CRM add-in with the click of a button.  It can also retrieve log files and event log information.

This will be really helpful in troubleshooting the Outlook Client connectivity. Kudos to the Dynamics CRM product team!

Looking forward for the future enhancement to this tool!

Full article from the CRM Support team:


Json2csharp Converter

With the recent updates of Web API in Dynamics CRM 2016 it seems like this RESTful API will be the future of Dynamics CRM API. One of the drawback of REST API is the absence of the service client creation out of WSDL (Ref:

For developers who are coming from C# background, we are comfortable with strongly typed classes compared to Javascript which is loosely typed. Today I found this useful online tool to convert Json to C#:

So for an example I’ll take this sample Json:

    "glossary": {
        "title": "example glossary",
        "GlossDiv": {
            "title": "S",
            "GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
                    "SortAs": "SGML",
                    "GlossTerm": "Standard Generalized Markup Language",
                    "Acronym": "SGML",
                    "Abbrev": "ISO 8879:1986",
                    "GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
                        "GlossSeeAlso": ["GML", "XML"]
                    "GlossSee": "markup"

Copy paste it into the web page, click the generate button. And...

Voila, C# classes are generated!

I hope this will be helpful for us to adopting the new CRM Web API!

CRM Online: Service Health Per Instance

This is a quick post. As recently I just registered for a new CRM Online trial instance for customer demo. I just noticed that there is a new tab called “Service Health” under the CRM Online Admin Center.


This feature is not that comprehensive yet, but is a good starting point to see on what happened on each instances level. I hope this can be enhanced to provide more details in the future.

I found out that this might be able to provide a better information around what happened around our CRM online instances.


Workaround for XrmToolBox (v1.2016.2.28) Connecting to CRM Online with Multiple Instances

XrmToolBox by Tanguy Touzard is my go to tool for lots of Dynamics CRM related productivity. It comes with lots of plugins that is an accumulative effort of the Dynamics CRM community.

Recently I’m working on a project on CRM Online 2016 with multiple instances (a couple of sandboxes and one production environment). The Dec 2015 version of XrmToolBox seems to introduce a new connection wizard. Somehow in this new wizard it detects the CRM organization name based on the name that specified in the URL. So here’s the story…

On the first screen when the connection wizard prompts the CRM Organization URL, typically I would enter my CRM online URL, e.g: However, when I tried to connect, I ran into the following error message:


Out of the Error Log from XrmToolBox tracing, I found out the following trace:

Microsoft.Xrm.Tooling.Connector.CrmServiceClient Information: 8 : Using User Specified Server 
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Information: 8 : Trying Live Discovery Server, (Oceania) URI is =
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Information: 8 : Found 2 Org(s)
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Information: 8 : looking for Org = mycrmonlinedev in the results from CRM's Discovery server list.

Then I came up with a conclusion that it could not find the CRM org based on the first part of the URL. Thanks to Tanguy who provide the answer to this problem:

As mentioned in the error message, if the unique org name (found in developer resources on web application) is different from the name used in the url, then you have to change the url to replace the org name with the unique org name.
A workaround is ready for next release so that you don’t have to do this manual operation

Then when I replace “mycrmonlinedev” part of the URL to the unique org name, which is a bit gibberish, I can connect to my CRM Online sandbox instance properly. (e.g:



Extending CRM Online Trial Without Support Ticket

I recently found out that there is a way to extend the Dynamics CRM trial instance for another 30 days without the need of logging a support ticket.

On your Office 365 Admin Portal (, navigate to Billing > Subscriptions > Select the trial product to be extended > Click on Extend link at the right hand side of the product pane.


Unfortunately it will ask for Credit Card Detail, but Microsoft would not charge the credit card for the extension.Credit_Card.png

If you don’t mind to enter the detail, it will be helpful to quickly extend the trial instance without the need of support ticket.


Dynamics CRM 2016 Solution: Flexibility in adding your existing entity!

Dynamics CRM 2016 comes with enhancement to the solution mechanism. The most favourite part of it is the patching and cloning, for more information about this, you can see Magnetism Team blog’s here.

Well, apart from the fancy feature above, now as system customizer/developer, we have a granular option of the entity on what we are going to include in the solution. Before CRM 2016, when we add any existing entity to a CRM solution, everything about that entity will be included in the solution. Now in CRM 2016, we can selectively add which part of the entity that relevant to this solution (this is in conjunction with the patching functionality). So now if I only want to make the change to one form, one view and a couple of fields it is now possible!


And the import process is considerably much faster this time, so it is a big improvement!