Microsoft Azure / Cloud Computing – Introduction

Cloud Computing enables companies to consume a complete resource – such as virtual machine, storage, or an application as a utility – just like electricity – rather than having to build and maintain computing infrastructure in-house.

Cloud provider provides the cloud infrastructure which is shared across multiple clients. Clients can select which service to use and only need to pay for that service, which is billed on-demand.

Cloud provider takes care of high availability (disk failure, power supply) and disaster recovery (natural or human disaster like fire, flood, etc.)

Advantages of using cloud computing

Rapid elasticity, only pay for the services used, reliability, economics of scale, etc.

Azure Regions Interactive Map

Types of Cloud Computing Services.

  • IaaS – Infrastructure as a service – Azure Virtual Machines, Azure Storage.
  • PaaS – Platform as a service – Azure Functions, Logic Apps, Azure Automation.
  • SaaS – Software as a service – Dynamics 365, SharePoint, Power Platform.

Types of Cloud computing deployment models.

Hope it helps..

Use Azure Data Factory V2 to load data into Dynamics 365

Let us take a simple example where we will set up an Azure Data Factory instance and use Copy data activity to move data from the Azure SQL database to Dynamics 365.

Login to Azure Portal.

Search for Data factories

Create a new data factory instance

Once the deployment is successful, click on Go to resource

Inside the data factory click on Author & Monitor

Click on Author in the left navigation

Create a new Pipeline

And drag the Copy data activity to it

Go to the Source tab, and create a new dataset.

Below is our Azure SQL database with contacts table which will be our source here.

Select Azure SQL Database as the source dataset.

Create a new linked service to specify the connection properties.

Specify the details to connect to the Azure SQL Database.

We have selected the contacts table here.

Similarly, let us define a new dataset for Sink which will connect to our Dynamics 365 Instance.

Select the Dynamics data set and specify the linked service.

Specify the details of the Dynamics 365 instance to connect to.

We have selected contact entity as the destination.

Within the Mapping tab, we can specify the fields to be mapped.

Below is how we have specified the mapping.

Click on Validate and after successful validation, click on Debug to run the pipeline.

Within the Output window, we can see the status.

After the successful run, we can see the contact records created inside Dynamics 365.

We can specify a trigger for the pipeline as shown below.

Publish All will publish the changes to the data factory.

Hope it helps..

Use Azure AD Conditional Access to block access by country (Dynamics 365)

In the previous post, we covered conditional access based on the device platform, here we’d look into how we can use the network location to block the access.

We can either use IP ranges or Countries / Regions for defining the location.

Login into the Azure Portal

Navigate to Azure Active Directory – Security – Named locations to define the location.

Here we are adding a new countries location record.

For the new location, we have selected India and UAE.

Next click on Conditional Access to define a new policy.

For Users and groups, we have selected a user named testuser1.

For Cloud Apps or actions, we have selected Common Data Service.

For Conditions, we have specified Locations condition with the Restricted Locations record that we had created earlier.

For Access Controls, we have selected Block access.

Enable and create the policy.

Before the policy was enabled, test user1 was able to access Dynamics 365.

After enabling the policy if we try accessing Dynamics 365 from either UAE or India location, we’d get the below message.

Same for the Dynamics 365 for Phones app.

Test user 3 to which policy doesn’t apply can still access Dynamics 365.

Hope it helps..

Using Azure Bot Service to create Bot

Using Microsoft Bot Framework

Azure Bot Service is an integrated environment that allow us to easily register, build, deploy our bots. It provides the required components and hosting environment for creating bots through Bot Builder SDK using either C# or JavaScript and connector service to connect to various channels.

Login to Azure Portal.

Search for Web App Bot

We have selected Basic Bot template.

After the Bot Web App is created, we have the option to either Download Bot Source Code to keep developing using Visual Studio or we can open it in online code editor.

Online Code Editor allows to update the source code within the App Service Editor

As the basic bot app template uses the Language Understanding Intelligent Services, we can log on to the Luis

There we can see the app.

With all the corresponding Intents, Entities and Utterances.

To test the bot either we can either download the emulator for testing locally or can test online using Web Chat.

Select Test in Web Chat

After we have tested it, next we add channel to our Bot, here we will add Skype.

Below are some of the configuration that can be applied for Skype.

Messaging gives the option of enabling the messaging, Calling let us to enable calling, groups allows us to add the bot to groups and Publish option allows to publish the bot and also submit it for review if it to be used by more than 100 contacts as shown below.

Clicking on Save publishes the bot and we can see the Skype added as one of the channels.

Click on Skype icon to add it to skype.

Add to contacts will add it to Skype and can start our conversation.

Hope it helps..

Changing the target runtime version of Azure Functions

Azure Functions 2.x runtime is based on .NET Core 2 from .NET Framework 4.7 in 1.x. So, any application migrating from 1.x to 2.x needs to make sure that they are using and referring the compatible code and libraries.

We can also update our Azure Functions to target the appropriate runtime using the below steps à

Inside Azure Portal, select the Function App, click on Application Settings within Platform Features tab.

We can specify the version number for the APP SETTING NAME – FUNCTIONS_EXTENSION_VERSION

~ tilde à indicates that the latest version of that major version.

Get all the details here

Hope it helps..

Publish as Azure Web Job Option missing in Visual Studio 2017

While trying to publish one of our console application to Azure as Web Job we couldn’t find the “Publish as Azure WebJob..” option

It was because Azure development tools were recently uninstalled from the system.

To install it, go to Windows à Program and Features à Select Visual Studio 2017 and click on Modify.

And select Azure Development for installation

Select Azure Cloud Services tool.

After installation it will ask for restart.

After restart we’d see the option added in our Visual Studio.

Hope it helps.

You are not authorized or do not have any subscriptions associated error while trying to access Kudo Sites in Azure

Today for one of our Azure WebJobs when we tried checking its log, we got the below error à

Seemed strange as being the Contributer of that Resource Group, I had access to all other functionality within that resource group.

After much struggle, in one of threads there was a suggestion to try in a different browser or in private browsing mode. And luckily that worked.

Out of all responses, this one makes the most sense for this issue

Hope it helps..

Stop an Azure Web Job using WEBJOBS_STOPPED and WEBJOBS_DISABLE_SCHEDULE configuration settings

We had one triggered web job running every 5 minutes that would pull the data from SQL On Prem DB and create lead records in CRM.

During testing we wanted to stop the running web job.

To do go to Application Settings for the App Service. Add WEBJOB_STOPPED and WEBJOBS_DISABLE_SCHEDULE setting with value 1.

We’d see our web job stop running.

Another option is to kill the process itself

Open à


Get all the details here

Hope it helps..

Update Schedule of existing Azure WebJobs (triggered)

Suppose we have following WebJob deployed in Azure of type Triggered.

And now we want to update its schedule.

To do so,

Open the App Service Editor

Update the CRON expression in settings.job (in case of scheduled web job), if the file is not there we can create and add it.

This makes the Webjob to run every 1 minute.

Back in our Webjob we can see the schedule updated.

Inside the logs à

More details –

Hope it helps..


Using log4net with Azure WebJobs

To get started, let us create a C# Console Application and add the NuGet Package for log4net.

Update the App.Config with log4net configuration.

The most important part here is value of file.

The D:\Home\LogFiles is the path where our WebJob can write to.

Inside our program.cs initialize the log4net.

Publish the WebJob to Azure.

Open the Kudo, we can see the Folder created

And our log file

Get all the details here

Hope it helps..

Using Azure Hybrid Connections to connect to SQL On-Prem Database from Azure WebJob.

Updated = 23rd September 2018.

  • Hybrid Connections allows Azure Web Sites and Services to securely connect to the on-premises resources hosted within the corporate network, without requiring any change to firewall or network.


Prerequisites: –

  • Azure Subscription
  • TCP/IP protocol needs to be enabled.
  • SQL Authentication (1433 Default Port for Default Instance)
  • Windows Server 2008 or later and outbound internet connection and can talk with LOB application – SQL Database.


  • Multiple Hybrid Connection Manager can be installed in separate server that can do the load balancing.
  • Hybrid connection implements Transport Layer Security between the cloud and the on-premise endpoint for data encryption.
  • Hybrid Connection Uses Shared Access Signature for securing the End Points.


Here we’d take a simple example of creating an Azure WebJob that will connect to the SQL On-Prem Database.

To start with, create a console application that connects to SQL On-Prem Database and pulls information from a table inside it.

Publish it as Azure WebJob.

Click on Publish to publish the WebJob.

Back in Azure Portal, we’d see our WebJob. Click on Run to start the WebJob. And click on Logs.

As expected we’d get the SQL Exception as Web Job will not be able to connect to the On-Prem Database.

Now let us configure Hybrid Connection to get the WebJob up and running properly. Inside the App Service select Networking and click on Configure your hybrid connection endpoints.

Click on Add hybrid Connection.

Here Endpoint Host will be the name of our OnPrem Machine\Server, Endpoint Port will be the Port for the SQL Server (1433 for the default instance).

Next step is to install and configure Hybrid Connection Manager.

Once installed, open the Hybrid connection manager and click on Add a new Hybrid Connection

Log in with the Azure Subscription Credentials and select the Hybrid Connection created there.

If everything is correct, it should show the status as connected.

*I had to restart the Azure Hybrid Connection Manager Service after adding the connection for the Azure status to show as connected

Now back in our WebJob, let us click on Run.

In logs,

we’d see the data successful fetched from our SQL On-Prem DB.

In case of named instance of SQL, we need to create a new hybrid connection with the specific TCP Port used by that named instance.

To find the port used by the named instance, open SQL Server Configuration Manager, select the named instance of SQL and copy the value of TCP Dynamic Ports.

This is how our Hybrid Connection string will look like

The other important point to remember is that the connection string used should also specify the port.

Hope it helps..

Using Azure SQL Data Sync to Sync On-Premise and SQL Azure Database

Suppose we have an Azure SQL DB named MyDB which we would like to sync with an On-Prem DB.

Here we’d be using Azure SQL Data Sync. The sync can be bi-directional, one way from Azure to On-Prem and On-Prem to Azure or Azure to Azure DB(s) as well.

In Azure Portal, select the Azure SQL DB and select Sync to other databases and click on Click on New Sync Group.

Specify values for the Data Sync Group.

We have selected existing database MyDB, selected Automatic Sync – On. The Sync frequency can be defined in seconds, minutes, hours and days – It needs to be between 5 minutes to 30 days.

Conflict Resolution can be Member Win or Hub Win. Hub here specifies the Azure SQL DB that we have selected here.

Next click on Add On-Premise database to specify the database to which we want to sync.

Here we need to specify the Data Client Sync Agent, which requires downloading and configuring the Sync Agent first.

Before installing the Data Sync Agent we need to install the following prerequisites

Make sure to download the X86 one.

Run the Data Sync Agent installer, specify the Account that can connect to the On Prem DB and finish the installation.

Back in Azure inside Sync group, click on Create and generate a key and copy the key.

Run the Data Sync Agent and click on Submit Agent Key and specify Agent key along with the credentials to access the Azure SQL DB.

Next click on Register button to register the On-Prem DB as shown below.

Once registered we can select the On-Prem SQL DB registered along with the Sync Directions.

As the last step, select Configure Sync Group and select the Hub Database and the table and column that we want to sync along any of the table of On-Prem DB.

The corresponding tables will be created in the database. For e.g. if we have selected Person table in our Hub Azure SQL Database, it will be created in the our On-Premise Database.

This completes the configuration.

We’d see the Sync running every 5 minutes as we had configured. Update\Insert any data on Azure SQL DB or On-Prem SQL DB, we’d see the same reflecting back in other DB in case of Bi-Directional Sync.


More details here

Hope it helps..

Using SQL Server Transactional Replication to move data from SQL Server (On-Prem) to Azure SQL


Let us say we want to move data from Table named MyTable and view MyView from my SQL Server DB On-Prem to one of the Azure SQL Database.

The components involved here would be Publisher that publishes this data, Distributor that holds the information about the data to be published and Subscriber who subscribes to the data.

For Transaction Replication to work, the Azure SQL DB or any subscriber needs to have the matching schema as the published table. This can be achieved through Snapshot Agent which applies the snapshot. Distribution Agent distributes this snapshot to the Subscribers.

Transaction Replication Log Reader Agent looks for any changes in the published data. This agent runs at the distributor for “Push” subscriptions. It can run continuously and or can be scheduled. It looks for Insert, Update, Delete operations or any schema changes and pushes this to the Subscriptions.

Let us start by configuring the Distributor first. The distributor can be at the local or remote server.

We’d be creating a local Distributor here.

Right-click the Replication and select Configure Distribution

We are using the local server as Distributor.

Click Next.

Click Finish to complete the wizard.

This creates the distribution database in our Local Server.

Now let us configure the Publication.

Right-click the publication and select new publication. SampleDB is the DB from whose table and view we want to publish.

Select SampleDb

Select Transactional Publication

Select the table and the view

As we are publishing a view, we get the below message

We can click on Add to specify any filtering on the data to be published.

We can specify if we want to snapshot to be created immediately so that it is available while defining subscriptions. We can also schedule the Snapshot Agent or we can run it continuously.

Here we are specifying SQL Server Agent account.

Specify Publication Name and click on Finish to create the publication.

Now let us create the Subscription.

Right-click the publication created earlier, and select new Subscription

Select the publication

We can specify the type of subscriptions either Push or Pull. In our case, we are selecting Push.

Select Add SQL Server Subscriber to add our Azure SQL DB as the subscriber here.

Connect to the Azure SQL DB.

Here MyDB is the Azure DB to which we want to push the data.

Now specify the account for the Distribution Agent and to connect the Azure SQL DB.

Select Agent schedule as Run Continuously.

Click Finish to create the subscription.

Back in our Azure SQL DB, we can see the table and the view created with the data.

In Job Activity Monitor, we can see the details.

REPL-LogReader, REPL-Distribution and REBP-Snapshot.

Now just to test it, let us add 2 new rows in our Sample DB’s MyTable.

Back in our Azure DB, we can see the data being added to it.

More details below

Hope it helps..

Sample code to upload file to Azure Blob Storage from CRM Online Plugin

Sharing a sample code which we can use to upload files to Azure Blog Storage from within a CRM Online Plugin. Here we’d be making use of the REST API to simplify things (instead of using Windows Azure Storage library) in our Plugin.

First, we will be creating a storage account of type blob storage and a container inside it.

Log in to Azure Portal

Click on Add to add a new storage account.

Create a new container in it to store the blob files

In Azure Portal – Storage Account, go to Access Keys and copy the key

And also note down the storage account name and container name which will be used to construct the URL.

We can also go to container, select its properties and copy the url.

Here we have written the plugin on Create of Annotation, which then retrieves the attachment and uploads its content to the container.

Let us first see it in action.

We have created a new note and attached a text file to it.

Going back to our portal, we can see the file in our container.

The sample code for the plugin.

using Microsoft.Xrm.Sdk;
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace MyTestPlugin

public class UploadFile : IPlugin
public void Execute(IServiceProvider serviceProvider)
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
// Obtain the target entity from the input parameters.
Entity noteEntity = (Entity)context.InputParameters["Target"];
byte[] doumentBody = Convert.FromBase64String(noteEntity.Attributes["documentbody"].ToString());
string content = Encoding.UTF8.GetString(doumentBody);
string fileName = noteEntity.Attributes["filename"].ToString();

// Upload the attached text file to Azure Blog Container
UploadFileToAzureBlobStorage(content, fileName);

catch (Exception ex)
throw new InvalidPluginExecutionException(ex.Message);

void UploadFileToAzureBlobStorage(string content, string fileName)

string storageKey = "storagekey";
string storageAccount = "storageaccountname";
string containerName = "strogaecontaninername";
string blobName = fileName;

string method = "PUT";
string sampleContent = content;
int contentLength = Encoding.UTF8.GetByteCount(sampleContent);

string requestUri = $"https://{storageAccount}{containerName}/{blobName}";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);

string now = DateTime.UtcNow.ToString("R");

request.Method = method;
request.ContentType = "text/plain; charset=UTF-8";
request.ContentLength = contentLength;

request.Headers.Add("x-ms-version", "2015-12-11");
request.Headers.Add("x-ms-date", now);
request.Headers.Add("x-ms-blob-type", "BlockBlob");
request.Headers.Add("Authorization", AuthorizationHeader(method, now, request, storageAccount, storageKey, containerName, blobName));

using (Stream requestStream = request.GetRequestStream())
requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);

using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
if(resp.StatusCode == HttpStatusCode.OK)
// successfully uploaded


public string AuthorizationHeader(string method, string now, HttpWebRequest request, string storageAccount, string storageKey, string containerName, string blobName)
string headerResource = $"x-ms-blob-type:BlockBlob\nx-ms-date:{now}\nx-ms-version:2015-12-11";
string urlResource = $"/{storageAccount}/{containerName}/{blobName}";
string stringToSign = $"{method}\n\n\n{request.ContentLength}\n\n{request.ContentType}\n\n\n\n\n\n\n{headerResource}\n{urlResource}";

HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(storageKey));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

String AuthorizationHeader = String.Format("{0} {1}:{2}", "SharedKey", storageAccount, signature);
return AuthorizationHeader;


Hope it helps.

Using Azure Functions for writing Scheduled Jobs for Dynamics CRM

Update -26 – Sep- 2018


In our previous post we saw how we can invoke CRM from within the Azure Function.

Using that knowledge, let us now write an Azure Function that will run periodically.

Here we will take a simple example of creating a lead record every 2 minutes. Obviously real world scenario would involve much complex scenario like checking the status of all the open records and update them daily something of that sort.

Another way of writing a scheduled job is using Web Job I have written about it over here.

Login to Azure Portal and create a new Function App

Create a new function with Timer and CSharp template.

function.json bindings defines the schedule for the timer, it take a CRON expression for value schedule.

CRON Expression format: –

If we want it to run every 2 minute

Back to our code let us click on Run and test it.

Now let us quickly plumb the code to create Lead in CRM.

Go to App Service Editor for the Function App and add new a file named project.json which refers to the CRM Nuget Package.

Sample code that creates the lead record in CRM.

using System.Net;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;

public static void Run(TimerInfo myTimer, TraceWriter log)
IServiceManagement orgServiceManagement = ServiceConfigurationFactory.CreateManagement(new Uri(""));

AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = "";
authCredentials.ClientCredentials.UserName.Password = "*******";
AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);

OrganizationServiceProxy organizationProxy = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);
Entity lead = new Entity("lead");
lead.Attributes["subject"] = "Lead Created at" + DateTime.Now ;

log.Info($"C# Timer trigger function executed at: {DateTime.Now}");

Inside CRM

To monitor our Azure Function please select Monitor

Click on live event stream to monitor it real-time.

To stop or disable the function, select Manage and click on function state Disabled.

Hope it helps..

Call Dynamics CRM from Azure Functions

Update -26 – Sep- 2018


Let us take a look at a simple Azure Function that refers our CRM assemblies and creates contact record in CRM.

Log in to Azure Portal, search for Function App and create a Function App.

Here we have specified WebHook + API and CSharp Template. Click on Create this function.

Select the function app, go to Platform features tab and click on App Service Editor.

Right click the function and add a new file named project.json. It is within this file we will refer our Nuget Packages that we need in our function.

Here we will reference the following Nuget Package for CRM

"frameworks": {
"dependencies": {
"Microsoft.CrmSdk.CoreAssemblies": ""

Back in our Function when we click on Save or Run, we can see the required assemblies being installed in our Log.

The sample code for the Azure Function (just for simplicity the values are all hardcoded)

using System.Net;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;

public static async Task Run(HttpRequestMessage req, TraceWriter log)
log.Info("C# HTTP trigger function processed a request.");

// parse query parameter
string firstname = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "firstname", true) == 0)

string lastname = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "lastname", true) == 0)

IServiceManagement orgServiceManagement = ServiceConfigurationFactory.CreateManagement(new Uri(""));

AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = "";
authCredentials.ClientCredentials.UserName.Password = "*****";
AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);

OrganizationServiceProxy organizationProxy = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);
Entity contact = new Entity("contact");
contact.Attributes["firstname"] = firstname;
contact.Attributes["lastname"] = lastname;
var contactId = organizationProxy.Create(contact);
// Get request body
dynamic data = await req.Content.ReadAsAsync();

string fullname = "";
return fullname == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, "Contact created in CRM " + contactId.ToString());

Let us now test our function.

The function expects 2 query string parameter firstname and lastname and creates the contact record in CRM.

In our CRM, we can see the contact record created.

Hope it helps..


A simple implementation using Azure Functions, Microsoft Flow, Microsoft PowerApps, Dynamics CRM and SendGrid

Let us  implement a simple scenario where we create a lead record in CRM which then talks with Flow (and Power App).

The Flow calls an Azure Function (Custom API) that sends mail to the lead’s email address using SendGrid

1) Let us create an Azure Function that uses SendGrid to send email to the lead’s email address.

Login to Azure Portal and create a new Function App.

Let us create a Function using Generic Web Hook CSharp template

To keep it simple let us only enable GET method. Go to Integrate tab and in Allowed HTTP Methods Select Selected Methods and check GET.

Also set mode as Standard and Authorization Level as anonymous, which means we do not need a API Key to be passed as query parameter to talk with the function.

Now let us add a new Output

Select SendGrid as the template

Click on Save.

Here we would need to define SendGridApiKey.

Go to SendGrid portal and create a free account over there

Create and API Key and copy it’s value.

Now go to Application Settings of the Function App and set this key value with SendGridApiKey as the key name.

Now let us go back to our code and update it to work with lead object and Mail class which would be used for sending email using SendGrid API.

Here first we are referring the SendGrid assembly, then getting fullname and email from query string and then creating Mail object.

Save and check the log if the compilation succeeded or not.

Testing our Function.

We can see the mail in the mail box.

This completes our first part.

2) Now let us create the Swagger definition for it which we will use in Power Apps and Microsoft Flows for using this Azure Function as Custom API.

Select our function and click on API definition.

Click on Function.

Update the generated API Definition Template with query parameter details and also test it.

As it is running successfully, click on Export to Power Apps + Flow

This opens up the new section that details the steps we need to follow for using our Azure Function with Power Apps and Microsoft Flow.

There click on Download button.

Click on Go to PowerApps

It opens up the PowerApps portal (asks for log in) and opens the New Connection page.

Upload the JSON Definition file for our Azure Function, provide name and description and click on Next.

Click on Create.

Let us quickly test our new connection.

Click on New App in our PowerApps web portal.

Select PowerApps Studio for Web. Let us create a Blank App Phone.

Add a new Data Source and select our Azure Function there.

To get the API Key go to our function and expand API Definition Key.

It works properly.

3) Now let us move to our last step, wherein we use it inside Microsoft Flow and integrate it with Dynamics CRM.

The good thing is to configure the same for Microsoft Flow, we do not have to do any extra step as both Microsoft Flow and PowerApps share the same connection infra.

Go to Microsoft Flow portal

We can find our Custom API already added there.

Let us create a new flow. Start with Dynamics 365.

When a record is created. Select Organization Name and Leads as the entity and click on Add an Action.

Search for our Custom API.

Select LastName and Email as Dynamic Content from the lead record created.

Click on Create Flow to create the flow.

Unfortunately, we get the below error

Let us go back to our Swagger Definition and update it.

We have updated it as following

Let us quickly test it, import it in Power Apps as new connection and come back to our Flow.

Edit the connection there and specify the API Key as we had done earlier inside Power Apps and update it.

Open Flow and quickly add the required steps and click on Create Flow.

We have successfully created our flow. Now let us test it.

Let us create a new lead record

Our flow runs and sends the mail

That’s it we are done with our simple implementation. The main purpose of this post was to show the integration possibilities which could help us design and implement real world complex scenarios.

Hope it helps..

How to – Post a JSON body in Swagger

Recently working with an Azure Functions , we had to define its REST Signature using Swagger to be able to use it within PowerApps.

The Azure Function expected the code query parameter basically the apiKey for the function and JSON Body with custom object named Lead having following properties as POST method.

  • topic
  • fullname
  • email

This is how we’d define our Lead Object and pass it as one of the parameters in the body.

swagger: '2.0'
version: 1.0.0
basePath: /
- https
- http
operationId: /api/MyLeadWebHook/post
- application/json
- application/json
- name: Lead
in: body
description: lead object
required: true
$ref: '#/definitions/Lead'
description: >-
Replace with Operation Object
description: Success operation
- apikeyQuery: []
description: Lead Object
type: string
description: full name
type: string
description: topic
type: string
description: topic
- fullname
- topic
- email
type: apiKey
name: code
in: query

We can use the Swagger Editor built-in with Azure Functions or to edit and test our Swagger.

Hope it helps..

Calling Azure Functions (GenericWebHook-Csharp) from CRM

In our previous post, we created a simple Azure Function using a free account. (1-hour limitation).

In this post, we’d use our trial Azure account to create a Function App for which we will configure Web Hook trigger and it outputs to Queue and Azure Blog Storage.

We will call this Function from Plugin on Post Create of Lead in CRM Online and pass Lead details to it. This detail will be then passed to Queue and a file inside Azure Blog Storage as Output from the Function.

Open the Azure Portal

Select Function App.

Create the Function App.

Click on + for Functions to create a new Function.

We’d select GenericWebHook-Csharp template here.

This creates a new Function nme MyLeadWebHook and it has mode set to Webhook and type as Generic JSON.

We can define Post as the only allowed method to call this function as shown below.

Update the code for the function by defining the Lead Object and deserialization logic as shown below.

#r is syntax for referencing the library. Here Newtonsoft.Json library is being referenced for deserialization.

Save and Run to check if it has compiled successfully or not. Click on Test tab to test the function by passing the JSON in the request body.

We can see below that our function has run successfully.

This finishes our Web Hook trigger part. Now let us define the Queue Output to it.

Select Integrate and click on New Output.

Select Azure Queue Storage template here.

Name the queue as leadqueue. This will automatically create a queue name leadqueue.

The parameter name here is outputQueueItem. We will update our code to pass the lead details to this parameter.

Before we update the code for our function let us add new output which saves the Lead details to a text file. Click on new output and select Azure Blog Storage.

Here outputBlob is the parameter to which we need to provide the lead details. In the path outcontainer is the name of the container within Blob and rand-guid generates a random guid for the file name. Here we have added the extension .txt.

Now we have our outputs defined, so let us go back to our code for the function and update it to pass values to both the output parameter one for queue and other for the blob.

#r "Newtonsoft.Json"

using System;
using System.Net;
using Newtonsoft.Json;
public class Lead
public string Topic { get; set;}
public string FullName { get; set;}
public string Email { get; set;}

public static async Task<object> Run(<span class="hiddenSpellError" pre="" data-mce-bogus="1">HttpRequestMessage</span> req, TraceWriter log, </object>
IAsyncCollector<Lead> outputQueueItem, TextWriter outputBlob)
log.Info($"Lead Information Recieved");

string jsonContent = await req.Content.ReadAsStringAsync();
var lead = JsonConvert.DeserializeObject<Lead>(jsonContent);

log.Info($"Lead named {lead.Topic} created for {lead.FullName} with email id {lead.Email}");

// add to queue
await outputQueueItem.AddAsync(lead);

// write to a text file in azure blog storage
outputBlob.WriteLine($"Topic: {lead.Topic}");
outputBlob.WriteLine($"Full Name: {lead.FullName}");
outputBlob.WriteLine($"Email: {lead.Email}");

return req.CreateResponse(HttpStatusCode.OK, new { message = "Lead Information Recieved" });

To test the code click on Test and select Run

Click on Monitor tab for the Function and select the log created for our test run. We can see the values for the parameters in the invocation details section.

Now let us write a plugin that runs on Post Create of lead and calls this Function App.

First let us get the URL for our function app. Go to Function and click on Get Function URL.

Our Function URL –

The code parameter is the Key that should be passed while calling the above URL.

Keys tab is where we can configure out Keys.

Below is code for our plugin.

using Microsoft.Xrm.Sdk;
using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;

namespace MyTestPlugin

public class Lead
public string Topic { get; set; }
public string FullName { get; set; }
public string Email { get; set; }

public class MyPluginClass : IPlugin
public void Execute(IServiceProvider serviceProvider)
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
// Obtain the target entity from the input parameters.
Entity entity = (Entity)context.InputParameters["Target"];

using (WebClient client = new WebClient())
// get the lead details
var myLead = new Lead();
myLead.Topic = entity.Attributes["subject"].ToString();
myLead.FullName = entity.Attributes["fullname"].ToString();
myLead.Email = entity.Attributes["emailaddress1"].ToString();

DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Lead));
MemoryStream memoryStream = new MemoryStream();
serializer.WriteObject(memoryStream, myLead);
var jsonObject = Encoding.Default.GetString(memoryStream.ToArray());

var webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";

// our function key
var code = "2QYP6xwCswMNmzJDFJdDE65ed1PdNBOj5Wlu4LbSpeSjs/58h1KLbg==";
// the url for our Azure Function
var serviceUrl = "" + code;

// upload the data using Post mehtod
string response = webClient.UploadString(serviceUrl, jsonObject);
catch (Exception ex)
throw new InvalidPluginExecutionException(ex.Message);


Let us create our lead record in CRM and test our Azure Function.

We can check the Monitor tab for our Function and check the logs and can see the Lead Information added to queue and also a text file created from our output parameters.

Our text file in the container.

Hope it helps..

Starting with a simple Hello “World” Azure Functions


In this post we’d have a quick look at the Azure Functions

Azure Functions can be simply defined as – Code and Event. Basically, we’d have an event on which our code will execute. We can create a function pipeline wherein one function acts as a trigger to another function which then triggers the next action passing the corresponding output.

Azure Functions are easy to write, we can write them inside our Azure Portal or can write in them using command line tooling or Visual studio and easily upload them.

They can be easily bind to existing services like SendGrid, OneDrive, DropBox etc.

And the most important aspect is the Pay only for what you use. Azure Functions comes with monthly free grant of 1 million requests and 400,000 GB-s of resource consumption per month.

The easiest way to try our Azure Functions is to go to Azure Functions Portal

Click on Try It For Free (this doesn’t require setting up Azure Trial or using our existing Azure Subscription).

However, this trial is just for 1 hour.

We’d select Web Hook + API as our scenario and C# as our language and click on create this function.

It will ask as us to choose an auth provider.

After successful authentication, we are presented with the function editor page

We have the function with the below sample code already configure for us. It basically looks for name parameter in either as query parameter or request body and append Hello to it as response.

Click on Run to test it.

Below we have passed Nishant Rana as the value for the query parameter name.

Clicking on the Get Function URL provides us with the url of this particular Funtion.

We can test it in browser or can use any of the extensions like Postman, Advanced Rest Client etc.

View files shows us all the files

Clicking in Integrate presents us with the option to configure the trigger for the function as well as option to define output for it

We can update our Azure Function to update only the Post request as show below.

We can define an output for this function by clicking on New Output.

As we are using free account we’d see many of the options disabled.

Manage section shows us the Key associated for this function.

It is the same key that is being used in the function url

To add a new function we can click the plus button.

Below are the different Function Template that are available.

Again, we have most of the options disabled as we are using free account.

As a next step, we’d create a free Azure account and create function that does something more meaningful.

Meanwhile –

Hope it helps..

Integrating Bot with Dynamics CRM (OAuth 2.0 Authentication)

Let us continue with our previous posts on understanding and implementing a simple bot that interact with Dynamics CRM using Microsoft Bot Framework

Till now we had hard coded our connection to CRM inside the bot application which was used to create lead records in CRM.

In this post, we will use OAuth2 authentication to connect to CRM Service (Web API).

We’d update our bot to use Sign-In Card. It will launch a web browser (web site which redirects user to authenticate to office 365) where user will enter the credentials and on successful authentication it will get the authentication token which it would then use to interact with CRM.

Here we would be using Web Site deployed in Azure that takes care of all the plumbing part.

We will be using Bot State Service here for saving Bot State. User can save bot state in this bot state service and can retrieve it. So, we would be passing the user id to the web site hosted to the azure and after we get the authentication token on successful authorization, we save this information in the bot in the bot state using SetUserData method. Back in our Bot app we will retrieve this authentication token saved in session state using GetUserData method and use it for interacting with CRM Web API.

Let us first create a ASP.NET Web Application which would be use for redirecting the user to authentication and saves the authentication token to the Bot State Service.

This creates our Web Application.

Add the following Microsoft.Bot.Builder Nuget Package in the project.

Also add a View named Authorize, which we will use are redirect URI for our Dynamics 365 App that will be registered to Azure Active Directory.

Before we start writing the code in our controller, we need to register dynamics 365 app with Azure Active Directory.

Follow the below post for that.

Now we have our required values i.e. client id, client key and end point URL

Add the following keys in web.config.

Here Client Id, Client Secret and EndPoint Url are the one we got when we registered our Dynamics 365 App. Here Microsoft App Id and Password are for our Bot Application.

Update the HomeController.cs and add below action methods Login and Authorize.

using Microsoft.Bot.Connector;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Configuration;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace AzureAuthWebApplication.Controllers
public class HomeController : Controller
public ActionResult Index()
return View();
public ActionResult Login(string userid)
// string userid in session
Session["botuserid"] = userid;
// CRM Url
string Resource = "";

AuthenticationContext authContext = new AuthenticationContext(ConfigurationManager.AppSettings["Authority"]);
var authUri = authContext.GetAuthorizationRequestUrlAsync(Resource, ConfigurationManager.AppSettings["ClientId"],
new Uri(ConfigurationManager.AppSettings["RedirectUri"]), UserIdentifier.AnyUser, null);
return Redirect(authUri.Result.ToString());

public async Task<ActionResult> Authorize(string code)
AuthenticationContext authContext = new AuthenticationContext(ConfigurationManager.AppSettings["Authority"]);
var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
code, new Uri(ConfigurationManager.AppSettings["RedirectUri"]),
new ClientCredential(ConfigurationManager.AppSettings["ClientId"],

// Saving token in Bot State
var botCredentials = new MicrosoftAppCredentials(ConfigurationManager.AppSettings["MicrosoftAppId"],
var stateClient = new StateClient(botCredentials);
BotState botState = new BotState(stateClient);
BotData botData = new BotData(eTag: "*");
botData.SetProperty<string>("AccessToken", authResult.AccessToken);

// webchat is the channel id. Make sure it is same in the bot application when we get the user data
await stateClient.BotState.SetUserDataAsync("webchat", Session["botuserid"].ToString(), botData);
ViewBag.Message = "Your Token -" + authResult.AccessToken + " User Id - " + Session["botuserid"].ToString();
return View();

public ActionResult About()
ViewBag.Message = "Your application description page.";

return View();

public ActionResult Contact()
ViewBag.Message = "Your contact page.";

return View();
<p style="text-align: justify;">

Publish the Web Application to Azure.

Now let us go back to our Bot Application and update the messagecontroller.cs class.

using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.FormFlow;
using Bot_Application1.Models;
using System;
using Bot_Application1.Dialogs;
using System.Collections.Generic;
using System.Web;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Bot_Application1
public class MessagesController : ApiController
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
if (activity.Type == ActivityTypes.Message)
if (activity.Text.ToUpper() == "LOGIN")
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity replyToConversation = activity.CreateReply();
replyToConversation.Recipient = activity.From;
replyToConversation.Type = "message";
replyToConversation.Attachments = new List<Attachment>();

List<CardAction> cardButtons = new List<CardAction>();
CardAction plButton = new CardAction()
// ASP.NET Web Application Hosted in Azure
// Pass the user id
Value = "" + HttpUtility.UrlEncode(activity.From.Id),
Type = "signin",
Title = "Connect"


SigninCard plCard = new SigninCard("Please login to Office 365", new List<CardAction>() { plButton });
Attachment plAttachment = plCard.ToAttachment();
var reply = await connector.Conversations.SendToConversationAsync(replyToConversation);
else if (activity.Text.ToUpper() == "GETUSERS")
// Get access token from bot state
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
StateClient stateClient = activity.GetStateClient();
BotState botState = new BotState(stateClient);
BotData botData = await botState.GetUserDataAsync(activity.ChannelId, activity.From.Id);
string token = botData.GetProperty<string>("AccessToken");

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

var retrieveResponse =
await httpClient.GetAsync("$select=fullname");
if (retrieveResponse.IsSuccessStatusCode)
var jRetrieveResponse =

dynamic systemUserObject = JsonConvert.DeserializeObject(jRetrieveResponse.ToString());

foreach (var data in systemUserObject.value)
Activity jsonReply = activity.CreateReply($"System User = {data.fullname.Value}");
await connector.Conversations.ReplyToActivityAsync(jsonReply);
Activity reply = activity.CreateReply("Failed to get users.\n\nPlease type \"login\" before you get users.");
await connector.Conversations.ReplyToActivityAsync(reply);
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity reply = activity.CreateReply("# CRM BOT Instructions \n\nlogin --> Login to Office 365\n\ngetusers --> Get all System Users in CRM");
await connector.Conversations.ReplyToActivityAsync(reply);

var response = Request.CreateResponse(HttpStatusCode.OK);
return response;

private IDialog<LeadModel> MakeLuisDialog()
return Chain.From(() => new LUISDialog(LeadModel.BuildForm));

internal static IDialog<LeadModel> MakeRootDialog()
return Chain.From(() => FormDialog.FromForm(LeadModel.BuildForm));

private Activity HandleSystemMessage(Activity message)
if (message.Type == ActivityTypes.DeleteUserData)
// Implement user deletion here
// If we handle user deletion, return a real message
else if (message.Type == ActivityTypes.ConversationUpdate)
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
else if (message.Type == ActivityTypes.ContactRelationUpdate)
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
else if (message.Type == ActivityTypes.Typing)
// Handle knowing tha the user is typing
else if (message.Type == ActivityTypes.Ping)

return null;
<p style="text-align: justify;">

Publish the Bot to Azure.

Now let us test the Bot.

Go to –

Open the Bot and click on Test.

Let us start the Chat.

On typing login the bot presents User with the Sign In Card. Click on Connect.

Sign in with your credentials.

Give permission to the app.

On successful sign-in –

Now type in getusers

It brings us all the System Users full name from our CRM Organization.

The extremely informative posts from which I learned about it

and following pluralsight training that helped in understanding OAuth and JWT concept.

Hope it helps..

Publishing Bot to Facebook Messenger

Let us continue with our previous posts on using Microsoft Bot Framework for writing a simple bot.

In our previous post, we published the bot app to Azure and also tested using Skype which is already configured.

In this post, we will be deploying the Bot to Facebook Messenger.

Sign in to Bot Developer Framework site

and open the bot application deployed.

Scroll down and we can see Facebook Messenger as one of the Channel available.

Click on Add.

Here we can see the guidelines and all the steps we need to do follow to configure the Facebook messenger

As a first step, we need to create a Facebook page for the bot

Click on the link and create a Facebook page

Next step is to create a Facebook App for the bot

Click on the below link to create the Facebook app.

Next step is to copy App ID and App Secret

Go to App Dashboard and copy these values. These values be used in the last step where we need to enter the credentials to authorize the app.

Next step is to enable the Messenger

Go to Dashboard and select Add Product.

Click on Get Started for Messenger.

Select the page from the dropdown and copy the token generated.

Next step is to set the Web Hook

Go to Messenger – Settings in Facebook App Dashboard.

And click on Setup

Go back to Configure Facebook Messenger page and copy the url and token from there.

Copy these values and paste it to New Page Subscription. Check the required subscription fields and click on Verify and Save.

It will show the status as complete on successful verification.

Now as a last step we need to enter our credentials

  • Facebook Page Id –

i.e. 403898986632435

All other values we had already copied earlier. So just passt those values.

And Click on Resubmit.

Once the credentials are validated. Click on “I’m done with configuring Facebook Messenger”.

Click on Message Us to start the conversation.

Hope it helps..

Publishing Bot to Azure and adding it to Skype (Microsoft Bot Framework)

Let us continue with our previous posts on using Microsoft Bot Framework to create a simple bot application that creates a lead in CRM.

In this post, we will be publishing our Bot application to Azure and also test it on Skype. Skype is one of the channel already configured for us.

Open the Azure Portal (Create a free trial if you do not have an account)

Right click on the application and select Publish.

Select Microsoft Azure App Service as the publish target.

Create the app service

Validate the connection and on successful connection click on Publish.

The published Bot Application –

Now to register our bot go to bot framework developer site

Sign in and Click on Register a bot

Enter all the required details.

Here URL will be the Destination URL of Azure where the Bot Application was published.

Click on Manage Microsoft App ID and Password

Click on Generate an Microsoft App ID and password.

Save the password and app id which will be used for configuration later.

Enter the App Id and click on Register to register the Bot.

We will get the message “Bot created” on successful registration.

Back in our bot application, open its web.config and specify value for app id and password and republish the app.

Once it is published successfully, inside our bot we can click on Test to check the connection.

We’d get the message “Endpoint authorization succeeded”.

Scrolling down we can see two channels web and skype already configured.

Click on Add to Skype to add the bot as a contact to skype.

Click on “Add to Contacts”

Sign in with your Skype Credentials.

Launch Skype.

We can see the Bot added to our contacts.

This is how we can easily publish the Bot to azure and add it to Skype.

Hope it helps..

Step by step – Upload files to Azure Blob storage

Here we will be creating a storage account of type blob storage and a container inside it. Then we will create a console application, add required nuget packages and upload a file to the container.

Log in to Azure Portal

Click on Add to add a new storage account.

Create a new container in it to store the blob files

Now we’d write a console app to connect to this container and upload a file.

Create a new console application and add references to below Nuget Packages.

  • Windows.Azure.Storage
  • Windows.Azure.ConfigurationManager

In Azure Portal – Storage Account, go to Access Keys and copy the connection strings for the storage account.

Inside console application add an appSettings section and add a key and paste the above copied connection string there.

The source code to upload the Blob file

// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(

// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("myblogcontainer");

// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("WeekendChamps.jpg");

// Create or overwrite the "myblob" blob with contents from a local file.
using (var fileStream = System.IO.File.OpenRead(@"C:\Users\Bliss\Downloads\WeekendChamps.jpg"))

The file uploaded in the container

Hope it helps..

List of all blog posts on CRM and Azure Integration

Configure Product Recommendations using Recommendations API in Dynamics 365

For configuring Product Recommendations first we need to enable the preview –

Go to Settings – Administration – System Settings – Previews

Select Yes and Click on OK.

As a next step, we need to create Cognitive Services for Recommendation API and connect it to CRM.

Go to Portal

Search and select Cognitive Services Accounts

Click on Add

Select Recommendation API and provide other details and click on Create.

From Overview, note down the Endpoint which will be used to configure the connection in CRM.

From Keys, copy value of the Key which will be used for configuring connection to CRM.

In CRM, go to Settings – Administration and click on Azure Machine Learning Recommendation Service Configuration.

Specify the value for the URL and Key we had noted down earlier, save the record and click on Test Connection to test the connection.

On Successful connection, we’d see Success message for Last Connection Status. Click on Activate to enable the connection.

Now we need to define\build the model for recommendations. For this go to Settings – Product Catalog and click on Product Recommendations.

We’d see a recommendation model with default values

The model will have Basked Data Entities already defined. We can edit\add new\ delete these existing configuration records for Basked Data Entities. Basked Data Entities recommendations are based on which products appear together.

For e.g. in below Opportunity record we can see 27 inch and 12 inch monitor opportunity products appearing together. It will look for all such line items records.

Similarly we have recommendation entities records configured which we can update.

Once done with the configuration, we need to click on Build Model Version to build the model.

It will create a corresponding model version record.

We can check its progress by refreshing it.

Here the model that we had defined has successfully build and it took around 6 minutes.

We can click on the Model Version to open the record to get the further details.

Next step would be to check the recommendations. For this click on Test Recommendations.

Pop up opens wherein we can select the Products and model version and click on Show Result to see what are the product recommendations.

Once satisfied with the test result, click on Activate to enable the recommendations.

We might get the below message in case we do not have good enough data in our system.

To see it in action, open an existing opportunity record , go to product sub grid and select a product and select Suggest Products.

A dialog box opens up that shows the Cross-Sell products and other details.

Get all the details here

Hope it helps..

Configure Automatically suggest knowledge articles using Cognitive Services Text Analytics (Preview) in Dynamics 365 (online)

As a first step, we need to set up Text Analytics Service and connect it to our CRM Online. Follow the below post for that

Next, we need to set up Knowledge Search field settings

For this go to Settings – Service Management and click on Knowledge Search field Settings

There click on New to create a new Search Model record.

Below we have specified case as our source entity. Click on Save.

Next, we need to define Keyword fields for our model, click on + to create a new text analytics entity mapping record.

To keep things simple, we have selected entity as Case and Field as Case Title based on which suggestions will be made. Save the record.

Click on Activate to activate the model.

Next, we need to modify the Case form to include knowledge base suggestions

Open the Conversation Tabs, go to Knowledge Base Search and select Text Analytics for Give Knowledge base suggestions as described below and publish the form

Open any of the case record, go to KB Records. Here based on the Case Title, the text analytics picks up the keyword “Delay” and shows/suggests the corresponding KB Articles matching that keyword.

Get all the details here

Hope it helps..

Configure Document Suggestions using Cognitive Services Text Analytics (Preview) in Dynamics 365 (online)

Let us take a simple example to understand how to configure Document Suggestion preview feature.

To do so first we need to enable Text Analytics Service, Connect it to our CRM Online and configure similar record suggestions. Please follow the below post for all the details.

Go to Settings – Document Management – Manage Document Suggetions

Select the entity for which we want to enable it, as we had our similar record suggestions enabled for Case we select the Case entity here.

Click on Apply.

Now as we already have Similar Record Suggestions configured for Case entity, for a case record with Delay keyword in its title we get the below suggestions

So, for Delay in Dispatch record we are getting Delay in service, delivery and shipment as suggestions as similar cases.

Now what we have done over here next is that we have attached document(s) to each of these case records.

For Delay in Dispatch case record –

For Delay in Service case record –

For Delay in Shipment record we have 2 document attached.

For Dispatch in Delivery case record we do not have any document attached yet.

Now let us open case with title “Dispatch in Delivery” and go to its Documents related records and click on Show Suggestions button

A dialog opens which list all the documents that are associated to the case records similar to the Delay in Delivery record i.e. all the remaining case records having delay keyword in its title.

Select documents and click on Copy.

Documents Copied to the Delay in Delivery record.

Hope it helps..