Dynamics 365 Articles

DYNAMICS CE WORKFLOWS SCHEDULING USING AZURE FUNCTIONS

A ‘making-dynamics guy’s life-easy‘ solution to schedule your Dynamics CE out of box workflows to run on particular frequencies is finally here!

System workflows are the best when it comes to doing a simple task without having to put our heads into writing hell a lot of coding. However, the real pain comes into scene when you want to schedule them as per your requirements. Well, if you’re wondering how you could make this work out in a simple way, here’s the good news – this is totally achievable using the winning combo of an Azure function with a timer associated with it. If you want to read more about the how Azure function works, you can use this link – https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview

Now, if you want to dive right in, you’re in the right place.

 

ADVANTAGES:

 

  1. Unlike other solutions, the usage of Azure functions allow you to enjoy the benefits of a server-less setup. These are perfectly designed to run without a server and to integrate and monitor jobs that run within CE.
  2. Connection to CE can be made by referring to the core SDK libraries using NuGet.
  3. It consumes less number of resources for running, without having to use custom entities in CE to configure the scheduler.
  4. Easy management of the functions that are set up. You can enable or disable them as and when required just by a button click.
  5. Detailed logging of successes and failures of the workflows that are being executed on frequencies
  6. Handles bulk jobs with a function timeout of 10 minutes. (how cool is that!)

 

PRE-REQUISITIES:

 

This list is surprisingly not long. All you need for this to be set up successfully is, an Azure Subscription or a free Azure trial login account to give it a go.

 

STEPS:

 

  1. Login to your Azure Account, from https://portal.azure.com. You will be able to see your Dashboard in the home screen.
  2. Click on ‘Create a resource’ option, located on the upper left-hand corner of the page.
  3. Type in ‘Function App’ in the search box that appears, enter all the required values and click on create. Once the function starts deploying, wait for the Deployment Succeeded message to appear in your notifications.

  1. Open the app that you just created and create a new function for the app. Make sure you select the type as ‘Timer Trigger’ while you create , as shown below

  1. Set a schedule timer using CRON expression which is displayed under the Integrate section of the function. The format of this expression will be {second} {minute} {hour} {day} {month} {day-of-week}.

I have set the timer expression as 0 */5 * * * *, which means that the workflow will run for every 5 minutes. To know more about different timer settings, refer this link – https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer.

 

  1. Connect to Dynamics CE by referring to the core SDK assemblies using NuGet. Go to Platform features tab on the function and click on App Service Editor. This will open up all the files in the folder in a new window. Create a new file called ‘project.json’ within the same function folder. Use the following code snippet to connect to the CE SDK assemblies.

{

“frameworks”: {

“net46”:{

“dependencies”: {

“Microsoft.CrmSdk.CoreAssemblies”: “8.2.0.2”

}

}

}

}

 

 

  1. We will then add configuration parameters in Application settings of the function, for the C# code to run. These parameters include the CRM instance URL that you are connecting to, the appropriate credentials for connection and the actual name of the workflow that needs to run on the scheduled time.

  1. Now, we add in the following piece of code that triggers the workflow specified in the configuration parameters using the credentials mentioned in the above step.

using System.Net;

using System.Configuration;

using Microsoft.Xrm.Sdk;

using Microsoft.Xrm.Sdk.Client;

using Microsoft.Crm.Sdk.Messages;

using Microsoft.Xrm.Sdk.Query;

 

 

public static void Run(TimerInfo myTimer, TraceWriter log)

{

IServiceManagement<IOrganizationService> orgServiceManagement = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(ConfigurationManager.AppSettings[“CRMinstance”]));

 

//Connect to the CRM instance

AuthenticationCredentials authCredentials = new AuthenticationCredentials();

authCredentials.ClientCredentials.UserName.UserName = ConfigurationManager.AppSettings[“CRMusername”];

authCredentials.ClientCredentials.UserName.Password = ConfigurationManager.AppSettings[“CRMpassword”];

AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);

 

//Retreive the service

IOrganizationService service = new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);

 

//Get the workflow GUID to run from workflow name

QueryExpression objQueryExpression = new QueryExpression(“workflow”);

objQueryExpression.ColumnSet = new ColumnSet(true);

objQueryExpression.Criteria.AddCondition(new ConditionExpression(“name”, ConditionOperator.Equal, ConfigurationManager.AppSettings[“CRMworkflow”]));

objQueryExpression.Criteria.AddCondition(new ConditionExpression(“parentworkflowid”, ConditionOperator.Null));

EntityCollection entColWorkflows = service.RetrieveMultiple(objQueryExpression);

if (entColWorkflows != null && entColWorkflows.Entities.Count > 0)

{

 

Guid workflowGuid = entColWorkflows.Entities[0].Id;

if(workflowGuid != null)

{

//Get the fetchxml string from Configuration

string entitySetting = ConfigurationManager.AppSettings[“CRMFetchString”];

FetchExpression fetchRecords = new FetchExpression(entitySetting);

 

EntityCollection recordsCollection = service.RetrieveMultiple(fetchRecords);

if (recordsCollection.Entities.Count > 0)

{

log.Info($”Records fetched : {recordsCollection.Entities.Count} at {DateTime.Now}”);

foreach (Entity e in recordsCollection.Entities)

{

ExecuteWorkflowRequest request = new ExecuteWorkflowRequest()

{

WorkflowId = workflowGuid,

EntityId = e.Id

};

log.Info($”Executed workflow successfully : {DateTime.Now}”);

 

// Execute the workflow.

service.Execute(request);

}

}

}

}

 

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

}

 

  1. You can test run the C# code you added in the above step to make sure there are no errors.

 

  1. The function is by default enabled, and it can be disabled anytime you want by clicking on the enabled/disabled toggle button under the Manage option of the function. (I have disabled my function and that’s the reason why it has prefixed (disabled) to my function name).

 

  1. The ‘Monitor’ option of the function allows you to check for successes and failures of the function including the detailed logs included in the code.

 

 

And, that is all! Your azure function will keep running the specified workflow until you disable it.

952

1

Asha


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Finding this useful? Please spread the word :-)

Follow by Email952
Facebook
Facebook
Google+
https://dynamics365society.uk/archives/3034">
LinkedIn