Call Dataverse API from within an Azure Function

Summary

Here is a quick bit of code to help with connecting to the Dataverse API from within Azure Functions.

The following steps need to be carried out:

  1. Register a new App in Azure Active directory. Assign the correct API permissions (Dataverse). Keep a note of the secret, appid (clientid) and the Dataverse environment.
  2. Assign a security role to the Application User (Search for the App registration from point 1).
  3. Create a new Azure Function, and ensure it compiles correctly.
  4. Use the following code snippet to connect to the Dataverse:

Add the PowerPlatform.Dataverse Assembly using Nuget, then add a using namespace:

using Microsoft.PowerPlatform.Dataverse.Client;

Add a Dataverse connection method

private static ServiceClient DataverseConnection()
{
    string clientId = Environment.GetEnvironmentVariable("client");
    string clientSecret = Environment.GetEnvironmentVariable("secret");
    string environment = Environment.GetEnvironmentVariable("environment");

    var connectionString = @$"Url=https://{environment}.dynamics.com;AuthType=ClientSecret;ClientId={clientId};ClientSecret={clientSecret};RequireNewInstance=true";
    var service = new ServiceClient(connectionString);
    return service;
}

Call the method as required

ServiceClient service = DataverseConnection();

The environment variables are located in the localhosts.json file:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "environment": "orge192010.crm11",
    "client": "d00ef5........b",
    "secret": "VEM8Q~........b"
  }
}

Full code

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.Xrm.Sdk;
using System;
using System.Threading.Tasks;

namespace StripeInterface
{
    public static class AzureFunction
    {
        [FunctionName("GetCustomerEvent")]
        public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            // Connect to Power Platform
            try
            {
                // Connect to Power Platform Source
                ServiceClient service = DataverseConnection();

                // Test connection
                Entity contact = new Entity("contact");
                {
                    contact["firstname"] = "Syed";
                    contact["firstname"] = "Hussain";

                    service.Create(contact);
                }
            }
            catch (Exception e)
            {
                log.LogInformation(e.ToString());
            }

            return new OkObjectResult("");
        }

        private static ServiceClient DataverseConnection()
        {
            string clientId = Environment.GetEnvironmentVariable("client");
            string clientSecret = Environment.GetEnvironmentVariable("secret");
            string environment = Environment.GetEnvironmentVariable("environment");

            var connectionString = @$"Url=https://{environment}.dynamics.com;AuthType=ClientSecret;ClientId={clientId};ClientSecret={clientSecret};RequireNewInstance=true";
            var service = new ServiceClient(connectionString);
            return service;
        }
    }
}

I was getting Could not load file or assembly error: system.text.encodings.web. To fix this, I opened up my Visual Studio Project file: Azureproject.csproj and added a line:

<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
      <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.13" />
    <PackageReference Include="Microsoft.PowerPlatform.Dataverse.Client" Version="0.6.1" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>