Azure Functions CosmosDB Output binding with Visual Studio 2017

Azure Functions CosmosDB Output binding

Create a new Azure Function in Visual Studio 2017

  1. Start Visual Studio 2017
  2. CTRL/STRG + Q
    a. Type „extensions“
    b. In the extensions and updates dialog search under Online for „Azure Functions and WebJobs Tools“
    c. Install extension
    d. Restart Visual Studio
  3. Create a new Cloud/Azure Functions Project in your „Work“-Folder.
    a. Name = „CBFuncAppLab“
  4. Right click project and select „Manage Nuget-Packages“
    a. Upgrade Microsoft.Net.SDK.Functions to 1.0.6
    b. Search online package: „Microsoft.Azure.WebJobs.Extensions.DocumentDB“ – 1.1.0-beta4
    c. DO NOT INSTALL „Microsoft.Azure.DocumentDB“! This will result in a binding issue, as WebJobs SDK uses a different instance of „Document“ class (v. 1.13.2)!

  5. CTRL+SHIFT+A to add a new file – Select „Azure Function Function“ (CTRL+E – function) under „Visual C# Items“
    a. Name the class „CosmosDBUpsertFunction.cs“
    b. Choose „Generic Webhook“ and click „OK“

Let’s upsert a single document to the collection

For this we need to modify the code like this

namespace CBFuncAppLab
{
    public static class CosmosDBUpsertFunction
    {
        [FunctionName("CosmosDBUpsertFunction")]
        public static object Run(
            [HttpTrigger(WebHookType = "genericJson")]
            HttpRequestMessage req,
            TraceWriter log,
            [DocumentDB("demodb", "democol",
                        CreateIfNotExists =true, 
                        ConnectionStringSetting = "myCosmosDBConnection")] 
                        out dynamic document)
        {
            log.Info($"Webhook was triggered!");
            var task = req.Content.ReadAsStringAsync();
            task.Wait();
            string jsonContent = task.Result;
            dynamic data = JsonConvert.DeserializeObject(jsonContent);
            if (data!=null)
            {
                document = data;
                return req.CreateResponse(HttpStatusCode.OK, new
                {
                    greeting = $"Will upsert document!"
                });
            }
            else
                return req.CreateResponse(HttpStatusCode.BadRequest, new
                {
                    error = "Document was empty!"
                });
        }
    }
}

Make sure you have declared all using statements

using System.Net;
using Newtonsoft.Json;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;

Open ‚local.settings.json‘ and configure the your connection string

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureWebJobsDashboard": "",
    "myCosmosDBConnection": "AccountEndpoint=https://YOURACCOUNT.documents.azure.com:443/;AccountKey=MASTERKEY-READWRITE;"
  }
}

Either in Azure Portal or with a tool like „DocumentDB Studio“ create a new collection „democol“ within „demodb“ Database in your CosmosDB Account.

Let’s try it!

Start your Azure Function App in the Debugger and fire up a tool like „Postman“.
In the Output Console you can find the URL for your Webhook. In my case:

Use Postman to do a POST request on this URL with a JSON document as body. F.E:

{
    "id":"apollak",
    "Name":"Andreas"
}

Verify the output in the console window and if the document got written to your documents collection.

Let’s upsert multiple documents to the collection

Now lets output multiple documents in one call. For this we use a parameter with the IAsyncCollector interface. For synchron methods you can use ICollector instead. Alter the code like so:

[FunctionName("CosmosDBUpsertFunction")]
public static async Task<object> Run(
    [HttpTrigger(WebHookType = "genericJson")]
    HttpRequestMessage req, TraceWriter log,
    [DocumentDB("demodb", "Items", 
    CreateIfNotExists = true, 
    ConnectionStringSetting = "myCosmosDBConnection")] 
    IAsyncCollector<dynamic> documents)
{
    log.Info($"Webhook was triggered!");

    string jsonContent = await req.Content.ReadAsStringAsync();
    dynamic data = JsonConvert.DeserializeObject(jsonContent);
    if (data!=null)
    {
        foreach(var document in data)
            await documents.AddAsync(document);

        return req.CreateResponse(HttpStatusCode.OK, new
        {
            greeting = $"Will upsert documents!"
        });
    }
    else
        return req.CreateResponse(HttpStatusCode.BadRequest, new
        {
            error = "No documents where provided!"
        });
}

Run this sample again and post an array of JSON Documents instead. Verify if the function works and the documents have been upserted to the CosmosDB collection.

[{
    "id":"apollak",
    "Name":"Andreas",
    "Likes":"Pizza"
},
{
    "id":"smueller",
    "Name":"Susi"
}]

Thnx and Enjoy
AndiP