Sonoma Partners Microsoft CRM and Salesforce Blog

Offload Processing with Azure Functions

Earlier this year, Microsoft announced Azure Functions which provide the ability to run code that can be triggered by events from within Azure or from third party systems or even scheduled at certain intervals.  There are many ways Azure Functions can be used to benefit your CRM system.  In this article, I will walk through how an Azure Function can be built and triggered from a plugin in CRM for asynchronous processing outside of the native CRM async service.

Note: Azure Functions are still in preview state and therefore provided “as-is” and may not be covered by customer support.

First, head to your Azure org and add a new resource.  Search for “Function App” in the filter.

image

Select Function App and click Create and then specify a unique name for your Function App and which resource group and plan to add it to.

In our scenario, we are going to trigger the function from a CRM plugin so we want to choose the “Webhook + API” scenario and I’ll be using C# for this example but JavaScript could be used as well if desired.

image

Now the Function App is created and a sample function is already setup with a Url that can be used to trigger the Function.  The sample Function looks for a “name” property in the request and returns a message back to the client application using the “name” property that was passed in.

image

With this basic sample, you could be good-to-go already, if you don’t need to interact back to CRM.  You could have your CRM plugin pass in the necessary data and let your Function do with what it needs, such as processing that data and then sending it off to a third-party system.

But what if you need to query CRM for more data or make some updates within CRM?  In order to do so, we need to do a little bit more work.

First, we’ll need to add some NuGet packages that our Function can reference to connect to the CRM API.  In order to do so, we need to add a project.json file to the Functions folder where it is hosted in Azure.

  • Click “Function app settings” at the bottom left of the Function app screen

image

  • Click “Go to App Service Settings” in the Advanced Settings at the very bottom of the screen

image

  • Under the “DEVELOPMENT TOOLS” section, click “App Service Editor”

image

  • Click “Go” on the next screen and it will open a new browser window
  • Expand your Function app node under the WWWROOT node then right-click and select “New File”

image

  • Type project.json for the file name
  • Update the project.json file with the following:

{
  "frameworks": {
    "net46":{
      "dependencies": {
        "Microsoft.CrmSdk.CoreAssemblies": "8.1.0.2",       
        "Microsoft.CrmSdk.XrmTooling.CoreAssembly": "8.1.0.2",
        "Microsoft.IdentityModel": "6.1.7600.16394",
        "Microsoft.IdentityModel.Clients.ActiveDirectory": "2.18.00"
      }
    }
   }
}

The necessary NuGet references for the CRM SDK are now added.  You can now either go back to the main Function app screen in Azure or just use the App Service Editor to edit the Function code in the run.csx file.  We will want to add the following namespaces to the top of the Function:

using System.Net;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Tooling.Connector;

Now we can utilize the CRM SDK to connect to our CRM environment with a connection string like so:

var orgUrl = "https://org.crm.dynamics.com";
var username = user@domain.com;
var password = "password";
var authType = Microsoft.Xrm.Tooling.Connector.AuthenticationType.Office365;

var crmSvc = new CrmServiceClient($@"ServiceUri={orgUrl};AuthType={authType};UserName={username};Password={password}");

Now we can use the org service to do whatever we need within CRM.  For this basic sample, we’ll just do a simple WhoAmIRequest and log the result to the Function app console to make sure everything is working correctly.

var request = new WhoAmIRequest();
var response = (WhoAmIResponse)orgService.Execute(request);
log.Info(response.UserId.ToString());

The final Function should look like so:

using System.Net;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Tooling.Connector;

public static void Run(HttpRequestMessage req, TraceWriter log)
{
    var orgUrl = "https://org.crm.dynamics.com";
    var username = "user@domain.com";
    var password = "password";
    var authType = Microsoft.Xrm.Tooling.Connector.AuthenticationType.Office365;

    var crmSvc = new CrmServiceClient($@"ServiceUri={orgUrl};AuthType={authType};UserName={username};Password={password}");

    var request = new WhoAmIRequest();
    var response = (WhoAmIResponse)crmSvc.Execute(request);
    log.Info(response.UserId.ToString());
}

 

Now click Run and in the Logs section you should see a Guid of your System User ID in between the Function started and Function completed statements.

image

You can then use a simple app like Postman to test submitting a request to the unique Url that Azure gave you for your Function app.  Once you submit the request, check your Logs in the Function app and you should see your System User ID logged again.

The last step would then be to build a standard CRM Plugin on the desired event and have it submit a request to your Function app Url to kick off the process.  Microsoft Flow could also be used to trigger an event from CRM and call your Function app without building any custom code at all.

There you have it, we can now utilize Azure Functions to free up some CRM processing but of course there are some caveats.

  • If you are on the “Dynamic” service plan, Azure Functions will currently only run for 5 minutes before timing out.  This still gives us 3 more minutes than an asynchronous plugin in CRM but be cautious of long running processes.
  • If an error occurs, there won’t be any ability to reprocess like there is with an asynchronous plugin in CRM.  You will need to build that into your Azure Function.
  • Lastly, Azure Functions aren’t free (they are cheap however).  If you have long running, memory intensive processes that will trigger often then you should consider the pricing.  Pricing details can be found here.  Microsoft gives 400,000 GB-s for free each month so if you have 1GB of memory allocated to your Function, it can run for 400,000 seconds per month without having to pay a single dime!
Topics: Microsoft Dynamics CRM Microsoft Dynamics CRM 2016 Microsoft Dynamics CRM Online