20
votes

I was following a walkthrough from microsoft learning on how to add an input binding with CosmosDb for an azure function, however when calling the function it keeps returning internal server error (500 http code).

The configuration of the azure function from function.json is:

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "Request",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "Response"
    },
    {
      "name": "bookmark",
      "direction": "in",
      "type": "cosmosDB",
      "databaseName": "func-io-learn-db",
      "collectionName": "Bookmarks",
      "connectionStringSetting": "learn_DOCUMENTDB",
      "id": "{id}",
      "partitionKey": "{id}",
      "sqlQuery": ""
    }
  ]
}

There is a learn_DOCUMENTDB configuration settings in the app service which has a valid connection string to cosmos db instance (was automatically created).

The error log entry says that:

Can't bind CosmosDB to type 'System.String'. Possible causes: 1) Tried binding to 'Microsoft.Azure.Documents.Client.DocumentClient, Microsoft.Azure.DocumentDB.Core, Version=2.9.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' but user type assembly was 'System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.

Is there something I do wrong?

11
What language you are using? I have post answer, it works well, but it is based on C# library.1_1
Have to set the value of partitionkey? On my side, partitionkey is testbowman.1_1
I have the same issue with the same MS Learn question, i tried classic mode but that seemed to break. I've added feedback for microsoft to fix it with a link to this stackoverflow page, hope they fix it.Sam Jones

11 Answers

29
votes

I had the same issue, turns out the new UI generates a different binding than the old one.

New UI:

{
  "name": "bookmark",
  "direction": "in",
  "type": "cosmosDB",
  "databaseName": "func-io-learn-db",
  "collectionName": "Bookmarks",
  "connectionStringSetting": "learn-0088a129-899f-4d18-b4db-5fa74daf1cc3_DOCUMENTDB",
  "id": "{id}",
  "partitionKey": "{id}",
  "sqlQuery": ""
}

Old UI:

{
  "type": "cosmosDB",
  "name": "bookmark",
  "databaseName": "func-io-learn-db",
  "collectionName": "Bookmarks",
  "connectionStringSetting": "learn-0088a129-899f-4d18-b4db-5fa74daf1cc3_DOCUMENTDB",
  "id": "{id}",
  "partitionKey": "{id}",
  "direction": "in"
}

Removing the

"sqlQuery": ""

part from the binding fixed it for me.

You can switch back to the old UI by clicking the "Having issues? Click to go back to the classic Function App management experience" on the app service overview page, as you can see here.

29
votes

For anyone still looking out for this, and if the above solutions don't resolve the issue.

I had the same issue with data not getting retrieved. Checked the function.json as suggested above. The issue though wasn't with the "sqlQuery" parameter.

According to the tutorial on Microsoft Learn, I had set the binding and the partition id values as "id" and "/id", when creating the Input DB binding. This showed up as-is in the function.JSON file. So my JSON file looked like: "id": "id", "partitionKey": "/id"

After looking at the above answers I changed the function.JSON Bindings of the DB to look like:

  "id": "{id}",
  "partitionKey": "{id}"

It was only after this change that it started working.

8
votes

Manually updating function.json to this:

 "id": "{id}",
 "partitionKey": "{id}",

worked for me, but as soon as the function was called or saved, it reverted the changes back to:

  "id": "id",
  "partitionKey": "/id",

and stopped working again. The only way I could get it to retain the changes is to edit the Integration section like so: settings for Input Binding Then the settings worked.

2
votes

Class1.cs:

using System;
using System.Collections.Generic;
using System.Text;

namespace FunctionApp52
{
    public class Class1
    {
        public string Id { get; set; }
    }
}

Function1.cs:

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.Extensions.Logging;
using Newtonsoft.Json;

namespace FunctionApp52
{
    public static class Function1
    {
        [FunctionName("DocByIdFromRouteData")]
        public static IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post",
                Route = "todoitems/{partitionKey}/{id}")]HttpRequest req,
            [CosmosDB(
                databaseName: "testbowman",
                collectionName: "testbowman",
                ConnectionStringSetting = "CosmosDBConnection",
                Id = "{id}",
                PartitionKey = "{partitionKey}")] Class1 item,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");
            log.LogInformation( "Id is: "+item.Id);
            if (item == null)
            {
                log.LogInformation($"ToDo item not found");
            }
            else
            {
                log.LogInformation($"Found ToDo item");
            }
            return new OkObjectResult("!!!!!!!!!!!!!!!!!!");
        }
    }
}

This is the item in cosmos db:

{
    "id": "bowmanid2",
    "PartitionKey": "bowmankey",
    "Description": "bowmandes",
    "testbowman": " "
}

(By the way, you need to set the value of patitionkey. On my side, it is testbowman.)

And then I send a request to http://localhost:7071/api/todoitems/ /bowmanid2

I can get:

enter image description here

2
votes

I was working trough the exercise that came after the one described here, where an output binding to CosmosDB was required. I was using Javascript (node.js) and could not get it to work even with the above suggestions - until I switched the Function Runtime v3 back to v2. This can be found under your function -> configuration -> function runtime settings.

1
votes

I don't have enough reputation yet to leave a comment instead of an answer, but I had this same problem and the answer from simandibalazs worked for me with one tweak. It seems the new UI also adds a field for "id":"" to the config and if you do not have an id specified there the same error will occur. In my case, I wanted to retrieve a set of items using ONLY the sqlquery, and to do so, I still had to remove the "id":"" line. If you want to retrieve all items you have to remove both of the following lines from the file.

"sqlQuery": ""
"id": ""
1
votes

Not enough reputation to comment BUT: I was experiencing some issues with the UI. Both in the bindings blade as in the code+test page. So I went to the app service editor on the function app itself to change these files.

0
votes

At the moment this is not possible to switch back to OLD UI (or at least I don't have this option) but this can be done directly one the portal by editing function.json file

enter image description here

You just need to remove

"sqlQuery": ""
0
votes

As @arno-peters replied in this question, there is an issue using a javascript environment. However, as he suggests, the runtime v2 is not available anymore (or at least not in sandbox for me). Anyhow, I just changed my environment from Node.js v14 to v12 and now it works using {id}.

MS definitely needs to upgrade its doc...

0
votes

In my case, all It needed was to prepend '/' before id in partition key. partitionkey :/id.

Furthermore, Keep SQLQuery empty if not required.

I created a new function in function app. Added input binding and I was getting the same error so I realized something is wrong with binding.

0
votes

Like a few other people here, I also don't have enough reputation to add a comment. For me to get this working I had to delete "partitionKey" and "collectionThroughput". This was for a Python Function writing to Cosmos DB.