Azure-functions-host: HttpTrigger not populating binding data from query

Created on 19 Mar 2018  路  30Comments  路  Source: Azure/azure-functions-host

Using v1, I have a function app that uses a route on the HTTP trigger and an id parameter for a CosmosDB input binding.

Here is the function.json for that function:

 "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "route": "document/{documentId}"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "document",
      "databaseName": "CookieBinge",
      "collectionName": "Binges",
      "connection": "datapointscosmosdb_DOCUMENTDB",
      "direction": "in",
      "id": "{documentId}"
    }
  ],
  "disabled": false
}

My app outputs one of the values from the incoming document. This app is written in C#.
I can use the test feature to pass in a document id and it runs successfully.
image

I'm building a new function using v2. The binding uses v2 settings.

{
  "type": "cosmosDB",
  "name": "document",
  "databaseName": "Ninjas",
  "collectionName": "Ninjas",
  "connectionStringSetting": "datapointscosmosdb",
  "direction": "in",
   "id": "{documentId}"
}

It fails with internal server errors if I try to test on the portal.
error: One or more errors occurred. (Worker process with pid 6236 exited with code 1) (Worker process with pid 4316 exited with code 1) (Worker process with pid 4728 exited with code 1)
When debugging in VS Code using the extension, the incoming bound document is not a single document but it is all of the docs in the collection.
I can see the documentId value in the context.bindingData.
I've been banging on this problem for a while and thought that maybe I've just hit a bug and it's not me. :)

Investigative information

Please provide the following:

  • Timestamp: ??? Don't know how to see this from context in vs code
  • Function App version (1.0 or 2.0-beta): 2.0-beta
  • Function App name: NinjaFunctions2
  • Function name(s) (as appropriate):
  • Invocation ID: "1273ffff-ac34-4e99-a2b3-f82b4b6a0194"
  • Region:
2.0 bug

All 30 comments

We have a tracking item Support single Document for binding for adding support to bind to a documentId. Also, here is a related thread with information on the workaround.

oh! My github search skills aren't so good I guess. glad to know it wasn't me! And I will just use a query for now. Thanks!

@pragnagopa @brettsam - I might be missing something, but how does the workaround in that thread in the forums or that tracked item you linked to apply to Julie's HttpTrigger question? Those links only seem to talk about CosmosDBTrigger supporting a single doc which isn't the same.

I've just run into something similar to Julie; trying to get a new c# compiled class v1 or v2 function with an HttpTrigger, to work with a Cosmos DB input binding to retrieve just the one document. I.e., I want to get a query parameter value from the input http trigger being passed in as a query parameter to the input binding as the document id to retrieve. Is that possible? Tried a few things and keep getting a "cannot bind" error to whatever I put in the value of id parameter for the cosmos binding attribute configuration.

Ok, to add some more, after some experimentation, using "Route" does make it work to map the id (ratingId in this case) to the Cosmos DB binding, i.e.:
c# [HttpTrigger(AuthorizationLevel.Function, "get", Route = "GetRating/{ratingId}")]HttpRequestMessage req, string ratingid, [DocumentDB("icedteadb", "ratings", Id = "{ratingId}",ConnectionStringSetting = "myCosmosDB")]object queryDoc, TraceWriter log)
So it's only query parameters parts of a JSON body that aren't being mapped from an HttpTrigger to binding expressions. Which I still think should work normally right?

@nzthiago --

  • You are correct, that issue was about the CosmosDBTrigger. This single-item input binding should still work as it did in v1.
  • You're also correct that it seems like the query parameters aren't getting bound to the binding data, so we can't find them.
  • Can you share the queries that work and don't work from your example above?

@julielerman -- To explain the behavior you're seeing -- I suspect what's happening is that the HttpTrigger binding isn't finding that documentId, so we see Id as null. If we have a null Id and a null SqlQuery for an input binding, we'll retrieve the entire collection.

@mathewc -- are there any known issues with binding data and HttpTrigger? I'm going to update this title as I suspect the problem is there, rather than with the Cosmos extension.

@brettsam i'm finding it with a standard query and have replaced my original binding with a sqlquery binding. The id binding parameter (above) doesn't seem to be working.

{
  "bindings": [

     {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "route": "doc/{documentId}"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "cosmosDB",
      "name": "document",
      "databaseName": "Ninjas",
      "collectionName": "Ninjas",
      "connectionStringSetting": "datapointscosmosdb",
      "direction": "in",
      "sqlQuery": "SELECT ninja.id, ninja.Name,ninja.ServedInOniwaban,ninja.DateOfBirth FROM ninja WHERE ninja.id= {documentId}"

    }
  ]
}

What does your HTTP request look like when it works?

@brettsam thanks for reopening and looking into this!

By "the queries that work and don't work from your example above", do you mean the HTTP call details? If so, basically any query parameters ( like ?ratingId=1) for a GET won't get mapped to a {ratingId} binding expression. Or, for a post, if I define a POCO with deserialization as per this doc doesn't seem to bind either.

So the workaround we went with that seems to work is a custom route in the HTTPTrigger attribute configuration (the Route = "GetRating/{ratingId}" section I had in my example), and then have that same {ratingId} as the Id value in the CosmosDB binding attribute config, then it works.
The call to this was a GET to the function url + /GetRating/ + the rating id.

@brettsam do you mean the http request to cosmosdb made by my function? gah ...can't figure out how to see that on my mac. Might have to learn how to use other features of postman. Is there an easy way to capture traffic so I don't have to spend a bunch of time in order to answer the q?

update ..olkay after 1/2 hr with wireshark i still can't figure out how to see outgoing traffic to the www . uggh

@julielerman -- I'm interested in the request you made to your function. I think @nzthiago has answered the question, though -- it looks like route values work, but query/body values don't. @fabiocav is going to take a look and see if something is broken with the binding wire-up in the HttpTrigger.

FYI - just retested with latest core tools that came out yesterday (with 2.0.11651-alpha runtime), Microsoft.NET.Sdk.Functions 1.0.11, and Microsoft.Azure.WebJobs.Extensions.CosmosDB 3.0.0-beta7, just to double check, but still the same: using route works, but not query/body.

just trying to understand this from a priority perspective. This is a straightup regression that could impact anybody migrating from V1 to V2, correct?

Also pinging @fabiocav since Brett mentioned he was going to look at this...

@paulbatum yes, I believe it would impact anyone going to v2 from v1. We ran into this a lot recently

That's correct. This is a V2 regression that must be addressed. I think this can be done this sprint, so I'm updating the milestone.

This has been addressed here: https://github.com/Azure/azure-webjobs-sdk-extensions/commit/e8589cec2b86b222199266dc3300c90e5180ba1a

@julielerman @nzthiago please let us know if you have any problems.

Thanks @fabiocav. How can I keep track of what Functions SDK version will come with this fix?

The SDK version remains the same with this. The tooling/runtime version is what changed. The fixes are in the CLI 2.0.1-beta.26 (VS Tools 2.1.0), and the runtime 2.0.11776

I just tried with 2.0.1-beta.26 (from my Mac).

With this config, using a route:

```c#
[FunctionName("GetRating")]
public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = "GetRating/{ratingid}")]HttpRequest req,
[CosmosDB("thiagodryrundb", "ratings", ConnectionStringSetting = "CosmosDBRatingsConnString", Id = "{ratingid}")] IceCreamRating rating,
TraceWriter log)


The host starts fine, but when I call it and pass it the rating id value as part of the route, it fails with:

[5/22/18 6:32:06 PM] Executed 'GetRating' (Failed, Id=6dd485a6-3189-400e-af05-66a93fd1ed1f)
[5/22/18 6:32:06 PM] System.Private.CoreLib: Exception while executing function: GetRating. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'rating'. Microsoft.Azure.DocumentDB.Core: The type initializer for 'Microsoft.Azure.Documents.UserAgentContainer' threw an exception. Microsoft.Azure.DocumentDB.Core: Error reading Darwin Kernel Version. Microsoft.Azure.WebJobs.Script: Object reference not set to an instance of an object.

This worked fine with CLI 2.0.1-beta.25.

With this config, removing the custom route (as  I want to pass in the rating id as a query parameter):

```c#
        [FunctionName("GetRating")]
        public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequest req,
                                        [CosmosDB("thiagodryrundb", "ratings", ConnectionStringSetting = "CosmosDBRatingsConnString", Id = "{ratingid}")] IceCreamRating rating,
                                        TraceWriter log)

It shows this error in the host logs when starting:

[5/22/18 6:35:32 PM] The following 1 functions are in error:
[5/22/18 6:35:32 PM] Run: Microsoft.Azure.WebJobs.Host: Error indexing method 'GetRating.Run'. Microsoft.Azure.WebJobs.Host: Unable to resolve binding parameter 'ratingid'. Binding expressions must map to either a value provided by the trigger or a property of the value the trigger is bound to, or must be a system binding expression (e.g. sys.randguid, sys.utcnow, etc.).

And if I call the function, it throws a 500 error back but with no extra logs by the host...

We did have the macOS issue with DocumentDB reported by another user, but that's not related to the original issue (we're tracking this separately). Have you had a chance to test this on Windows?

Just tested the same project on Windows.

With the route set to "GetRating/{ratingid}" it works fine in CLI 2.0.1-beta.25, but in CLI 2.0.1-beta.26 it doesn't show any errors when starting but when calling the function it throws this (doesn't seem to like the IceCreamRating POCO):

[5/23/2018 3:34:44 PM] Executing 'GetRating' (Reason='This function was programmatically called via the host APIs.', Id=f98eae12-67a6-41d0-a474-2871393fbe24)
[5/23/2018 3:34:45 PM] Executed 'GetRating' (Failed, Id=f98eae12-67a6-41d0-a474-2871393fbe24)
[5/23/2018 3:34:45 PM] System.Private.CoreLib: Exception while executing function: GetRating. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'rating'. Microsoft.Azure.DocumentDB.Core: The type initializer for 'Microsoft.Azure.Documents.UserAgentContainer' threw an exception. Object reference not set to an instance of an object.

With the route set to null I get that same warning below about binding parameter ratingid, and the function can't even be called (both in in CLI 2.0.1-beta.25 and 26):

[5/23/2018 3:38:29 PM] The following 1 functions are in error:
[5/23/2018 3:38:29 PM] Run: Microsoft.Azure.WebJobs.Host: Error indexing method 'GetRating.Run'. Microsoft.Azure.WebJobs.Host: Unable to resolve binding parameter 'ratingid'. Binding expressions must map to either a value provided by the trigger or a property of the value the trigger is bound to, or must be a system binding expression (e.g. sys.randguid, sys.utcnow, etc.).

The behavior you're seeing with without the route set is expected (if I correctly understand what you mean).

For the first issue, this seems pretty specific to your current setup and not currently caught by our tests/validation. Would you mind sharing more details in a different issue so we can try to isolate this and get a repro?

Without the route is what I expected to work without seeing that warning. It's what seems to work for Functions v1 (i.e., being able to bind from a query parameter in an HttpTrigger, or from a value in an inbound json in the body of a POST in an HttpTrigger, to a binding parameter in the input binding of cosmosdb), as per the earlier discussion here:
https://github.com/Azure/azure-functions-host/issues/2554#issuecomment-376970910

I think I misunderstood what you meant on the previous comment, but that shouldn't be the behavior in V1. Query access would be supported there using the dotted notation, in this case, you'd need to bind to a parameter named {Query.ratingid}.

In V1, having just ratingid in the expression should result in a similar failure.

Met with @fabiocav offline. Indeed {Query.ratingid} works for the Id field of the CosmosDB input binding. It didn't work inside SqlQuery though and Fabio will start an investigation.

Does {Query.ratingid} work for SqlQuery in v1? I suspect not.

PR https://github.com/Azure/azure-webjobs-sdk-extensions/pull/354 was opened a while back by @anthonychu. The goal was to get headers working with SqlQuery, but it exposed some flaws in our binding policy system and we ended up punting it. In short, it was really hard to mimic the behavior of other bindings without doing a lot of crazy stuff. This affects the Table binding's queries as well.

I'm realizing now that I never created a corresponding issue, so I've done that here: https://github.com/Azure/azure-webjobs-sdk/issues/1726

No it doesn't seem to; In v1 I get the following error: Exception while executing function: GetRatings -> Exception binding parameter 'ratings' -> Error while accessing 'userid': property doesn't exist.
It does seems strange to have it work inside Id but not SqlQuery

Agree. We'll need to fix it.

For a little background -- SqlQuery (and Table's query) has custom logic for preparing the query payload (https://github.com/Azure/azure-webjobs-sdk-extensions/blob/dev/src/WebJobs.Extensions.CosmosDB/CosmosDBSqlResolutionPolicy.cs), and it wasn't designed for nested properties. The context we're given doesn't have enough information for us to build up the SQL query in the way we need to.

@brettsam is there a linked issue to track the fix for this one? If not I can create (on the Cosmos extension? on the host?)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ElvenSpellmaker picture ElvenSpellmaker  路  3Comments

mathewc picture mathewc  路  3Comments

JasonBSteele picture JasonBSteele  路  3Comments

paulbatum picture paulbatum  路  4Comments

helgemahrt picture helgemahrt  路  4Comments