Afshin Gh
Afshin Gh

Reputation: 8198

Accessing DocumentDb from Azure Functions with dynamic DocumentId

Here is my function.json:

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "webHookType": "genericJson",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "documentDB",
      "name": "inputDocument",
      "databaseName": "MyDb",
      "collectionName": "MyCol",
      "partitionKey": "main",
      "id": "{documentId}",
      "connection": "MyDocDbConnStr",
      "direction": "in"
    }
  ],
  "disabled": false
}

And here is my run.csx:

#r "Newtonsoft.Json"

using System;
using System.Net;
using Newtonsoft.Json;

public static async Task<object> Run(HttpRequestMessage req, TraceWriter log, dynamic inputDocument)
{

    return req.CreateResponse(HttpStatusCode.OK, $"doc title is {inputDocument.title}");
}

Everything works fine if I define a fixed value for my document id in config.

But when I want to use a dynamic document id and use {documentId}, I get this error:

No binding parameter exists for 'documentId'.

My post data is:

{
    "documentId": "002"
}

How can I send DocumentId to my Azure Function and get associated item from DocumentDb?

Upvotes: 2

Views: 2239

Answers (2)

mathewc
mathewc

Reputation: 13568

To use custom parameters in C# binding expressions, those properties must be defined on the type your trigger input is bound to. Since you want to bind to documentId from the input payload, we define an Input POCO with a corresponding DocumentId property. Here's a working sample:

#r "Newtonsoft.Json"

using System;
using System.Net;
using Newtonsoft.Json;

public class Input
{
    public string DocumentId { get; set; }
}

public static HttpResponseMessage Run(Input input, 
              HttpRequestMessage req, dynamic document, TraceWriter log)
{
    if (document != null)
    {
        log.Info($"DocumentId: {document.text}");
        return req.CreateResponse(HttpStatusCode.OK);
    }
    else
    {
        return req.CreateResponse(HttpStatusCode.NotFound);
    }
}

And here is the corresponding function.json:

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "webHookType": "genericJson",
      "name": "input"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "documentDB",
      "name": "document",
      "databaseName": "ItemDb",
      "collectionName": "ItemCollection",
      "id": "{documentId}",
      "connection": "test_DOCUMENTDB",
      "direction": "in"
    }
  ]
}

Upvotes: 4

Akos Nagy
Akos Nagy

Reputation: 4359

A solution could be to parse the post data yourself. Something like this:

public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
{
    string jsonContent = await req.Content.ReadAsStringAsync();
    dynamic data = JsonConvert.DeserializeObject(jsonContent);
    return req.CreateResponse(HttpStatusCode.OK, $"doc title is {data.documentId}");
}

Then if you have the documentId, you can use the .NET Client SDK for DocumentDb or the REST API just like you would from a Console App.

Upvotes: 1

Related Questions