Dynamics CRM and Azure Scheduler – Breakthrough!

In this series of articles I’m setting up a scenario in which I hook up Dynamics CRM to the Azure Scheduler. My goal is to use the Azure Scheduler to start an Azure web job that will interact with Dynamics CRM.

In the previous article I managed to authenticate with Azure using REST. Furthermore I did my first steps in reading the Azure Scheduler job collection and creating a new job. Creating a job failed and I ended up with with error 403.

Breakthrough

Tonight I decided to pick up the previous effort where I left off. I decided to rewrite the code, embrace the async / Task<> / await pattern in order to get the complete response from the actions I called.
I found a good async example at dotnetperls.com. Using the pattern in the example I was able to call the async methods (required for getting and putting REST requests) from a synchronous function.

I implemented the Get function, in order to get a list of all jobs I created. The Get function is called from within the Execute function. As you can see in the Execute function, the async function Get is called by using a Task<> . The task.Wait() ensures that the synchronous function will wait until the async task has been completed.

private static void Execute(string subscriptionId, string jobCollectionId, string jobId, string bearerToken)
        {
 
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("Authorization", "Bearer " + bearerToken);
            client.BaseAddress = new Uri("https://management.azure.com/");
 
            Task<string> task = Get(client, subscriptionId, jobCollectionId);
            task.Wait();
 
            Task<string> task2= MakeARMRequest(client, subscriptionId,jobCollectionId,jobId);
            task2.Wait();
        }
 
 
        private static async Task<string> Get(HttpClient client, string subscriptionId, string jobCollectionId)
        {
            var url= $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/CS-WestEurope-scheduler/providers/Microsoft.Scheduler/" + 
                     $"jobcollections/{jobCollectionId}/jobs?api-version=2016-01-01";
 
            var response = await client.GetAsync(url);
            return await response.Content.ReadAsStringAsync();
        }

Running the code, I got the following json data. A little victory!

Azureasync1

From there on I implented the Async pattern on the function in which I want to create a new job. Running the code resulted in the following error message:

Azureasync2

A stange message, as the credentials I send with the REST call are the same credentials I use to get the list of jobs. A quick lookup in the MSDN documentation learned me that I was using an old api-version.

I decided to switch to the lastest version (2016–01–01), and gave the code another shot.

Azureasync3

Bummer! another error. But wait, it looks like the json data I send is in a wrong format. It turned out that the json data format was updated as well.

I changed the code and ran it again….

private static async Task<string> MakeARMRequest(HttpClient client, string subscriptionId, string jobCollectionId, string jobId)
        {
            var url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/CS-WestEurope-scheduler/providers/Microsoft.Scheduler/" +
                      $"jobCollections/{jobCollectionId}/jobs/{jobId}?api-version=2016-01-01";
           
            var data = "{" +
                       "  \"properties\": { " +
                       "    \"startTime\": \"2015-03-31T00:08:00Z\", " +
                       "    \"action\": { " +
                       "       \"request\": {   " +
                       "          \"uri\": \"http://bing.com\", " +
                       "          \"method\": \"GET\", " +
                       "          \"headers\": {} " +
                       "       }, " +
                       "       \"type\": \"http\", " +
                       "       \"retryPolicy\":{\"retryType\":\"Fixed\",  \"retryInterval\":\"PT1M\", \"retryCount\":2} " +
                       "    }, " +
                       "    \"state\": \"enabled\", " +
                       "    \"recurrence\": { " +
                       "       \"frequency\": \"hour\", " +
                       "       \"interval\": 1 " +
                       "    } " +
                       "  } " +
                       "}";

            var content = new StringContent(data, Encoding.UTF8, "application/json");
            content.Headers.Add("x-ms-version", "2016-01-01");
         
            var response = await client.PutAsync(url, content);
            return await response.Content.ReadAsStringAsync();
        }

I received a nice json message indicating that a new job had been created.
* Victory! *

Azureasync4

Running the Get method again learned me that the new job was added to the job collection.

Azureasync5

This paves the way for me to use the Azure Scheduler from within CRM, what I intend to do in the next article.

This is exact the reason why I want to use REST instead of the Azure .NET sdk.
Using the Azure .NET sdk would require me to use ILMERGE to merge different assemblies into a single dll that I could upload to Dynamics CRM. While REST calls can be handled with the System.Net.Http namespace. This will result in much smaller Dlls, with less dependencies and less error prone.

Anyway, what I learned tonight was:

  • it is important to use the async / Task<> / await patterns when getting and putting REST calls.
  • you always have to check if the Azure documentation on MSDN has been updated since the last time you accessed it. Stick with the latest version!

 

One thought on “Dynamics CRM and Azure Scheduler – Breakthrough!

  1. […] Dynamics CRM and Azure Scheduler – Breakthrough! […]

Leave a Reply

Your email address will not be published. Required fields are marked *