How to make Azure Functions + Dataverse Service Client

In this blog post, we will learn how to make Azure Functions for hosting APIs that will be used to connect with Dataverse (via Dataverse Service Client) and possibly other functions. Even though in Dataverse we actually can create custom APIs to do the same thing (but we need to merge third-party libs if any), many pure Dataverse Developer against it. So, make the APIs (using Azure Functions + Dataverse Service Client) outside the Dataverse become an alternative option. For those who don’t know what is Azure Functions, it is a deployment model for APIs (pay per execution) that use App Service behind it (which makes it more simple). Without further a do, let’s get into it!

Create The Project

If you have not yet set up your machine, you need to install the template. Open your command prompt, and then run the below command:

dotnet new --install "Microsoft.Azure.WebJobs.ProjectTemplates"

Once installed, you can CD to the directory that you wanted. Then you need to run the below command to create the DemoFunction folder with the C# project files inside it:

dotnet new func -o DemoFunction

After the project is successfully created, open the DemoFunction folder and you can double click the DemoFunction.csproj (I’m using VS Studio). Then you can install Microsoft.PowerPlatform.Dataverse.Client NuGet package for the demo project:

Install Microsoft.PowerPlatform.Dataverse.Client NuGet package

Besides that NuGet package, you also need to make sure to install these (taken from DemoFunction.csproj):

		<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
		<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
		<PackageReference Include="Microsoft.PowerPlatform.Dataverse.Client" Version="1.0.4" />

In the next step, you need to right-click on the project > Add > choose Azure Function > name it as CreateContact.cs. Once you click Ok, it will show another dialog. There, you can choose the Http Trigger > set the Authorization level as “Function” and click Add button:

Create Http trigger function

Then modify the code as below:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.Xrm.Sdk;
using Newtonsoft.Json;

[assembly: FunctionsStartup(typeof(DemoFunction.Startup))]
namespace DemoFunction
    public class Startup : FunctionsStartup
        public override void Configure(IFunctionsHostBuilder builder)
            var configuration = builder.GetContext().Configuration;

                .AddScoped<IOrganizationServiceAsync2>(_ =>
                    new ServiceClient(configuration["DataverseConnectionString"]));

        public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)

    public class CreateContact
        private readonly IOrganizationServiceAsync2 _crmService;

        public class Request
            public string FirstName { get; set; }
            public string LastName { get; set; }

        public class Response
            public Guid Id { get; set; }

        public CreateContact(IOrganizationServiceAsync2 crmService)
            _crmService = crmService;

        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req)

            var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var data = JsonConvert.DeserializeObject<Request>(requestBody);

            var contact = new Entity("contact")
                ["firstname"] = data.FirstName,
                ["lastname"] = data.LastName

            var id = await _crmService.CreateAsync(contact);

            return new JsonResult(new Response { Id = id });

In the above code, you can see that we use a dependency injection pattern where every time we need IOrganizationServiceAsync2, we will return a new Dataverse Service Client based on the connection string from the “DataverseConnectionString” configuration. The logic for the function is also very straightforward. Every time we receive a POST request (the body needs FirstName and LastName), we will create a Contact in Dataverse and return the Id.

In the next step, we just need to deploy this + create the Azure Function App!

Deploy and Execute the API!

Go to your > create a resource group (best practice):

Right-click on the DemoFunction project > Publish > Add a publish profile >on the Target, choose Azure > on the Specific target choose Azure Function App (Windows) > Sign in to your Azure instance (if you have not yet done it) > then you can set up like below (I use default name) > click Create:

Create Function App

Once created, you can click Next > skip the APIM, and don’t forget to publish it.

Go to your > go to the Function App that you created in the previous step > go to Configuration blade > hit + New application settings > name the configuration “DataverseConnectionString” and value with your valid Dataverse connection string (if you don’t know how to do it, ping me 😎) > click OK > don’t forget to click Save after that:

Create new configuration named DataverseConnectionString

To test the API, you need to go to App keys and get the default key:

Get the key

Then in Postman, you can define like the below request (POST, URL +”?code=[key_in_the_previous_step]“, and the JSON Body with params firstName + lastName):

Demo Result

Happy CRM-ing!


2 thoughts on “How to make Azure Functions + Dataverse Service Client

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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