Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpTrigger not populating binding data from query #2554

Closed
julielerman opened this issue Mar 19, 2018 · 29 comments

Comments

Projects
None yet
7 participants
@julielerman
Copy link

commented Mar 19, 2018

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:
@pragnagopa

This comment has been minimized.

Copy link
Contributor

commented Mar 19, 2018

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.

@pragnagopa pragnagopa closed this Mar 19, 2018

@julielerman

This comment has been minimized.

Copy link
Author

commented Mar 19, 2018

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!

@nzthiago

This comment has been minimized.

Copy link
Member

commented Mar 27, 2018

@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.

@nzthiago

This comment has been minimized.

Copy link
Member

commented Mar 28, 2018

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.:

 [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?

@brettsam brettsam reopened this Mar 28, 2018

@brettsam

This comment has been minimized.

Copy link
Member

commented Mar 28, 2018

@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 brettsam changed the title Cosmos DB Input binding for document doesn't filter on id - v2 HttpTrigger not populating binding data from query Mar 28, 2018

@brettsam brettsam added bug 2.0 labels Mar 28, 2018

@julielerman

This comment has been minimized.

Copy link
Author

commented Mar 28, 2018

@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}"
     
    }
  ]
}
@brettsam

This comment has been minimized.

Copy link
Member

commented Mar 28, 2018

What does your HTTP request look like when it works?

@nzthiago

This comment has been minimized.

Copy link
Member

commented Mar 28, 2018

@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.

@julielerman

This comment has been minimized.

Copy link
Author

commented Mar 28, 2018

@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?

@mathewc mathewc added this to the Triaged milestone Mar 28, 2018

@julielerman

This comment has been minimized.

Copy link
Author

commented Mar 28, 2018

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

@brettsam

This comment has been minimized.

Copy link
Member

commented Mar 28, 2018

@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.

@nzthiago

This comment has been minimized.

Copy link
Member

commented Mar 30, 2018

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.

@paulbatum

This comment has been minimized.

Copy link
Member

commented Apr 18, 2018

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

@paulbatum

This comment has been minimized.

Copy link
Member

commented Apr 18, 2018

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

@nzthiago

This comment has been minimized.

Copy link
Member

commented Apr 19, 2018

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

@fabiocav

This comment has been minimized.

Copy link
Member

commented Apr 19, 2018

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.

@fabiocav fabiocav modified the milestones: Triaged, Sprint 22 Apr 19, 2018

@fabiocav

This comment has been minimized.

Copy link
Member

commented May 21, 2018

This has been addressed here: Azure/azure-webjobs-sdk-extensions@e8589ce

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

@fabiocav fabiocav closed this May 21, 2018

@nzthiago

This comment has been minimized.

Copy link
Member

commented May 22, 2018

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

@fabiocav

This comment has been minimized.

Copy link
Member

commented May 22, 2018

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

@nzthiago

This comment has been minimized.

Copy link
Member

commented May 22, 2018

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

With this config, using a route:

       [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):

        [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...

@fabiocav

This comment has been minimized.

Copy link
Member

commented May 22, 2018

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?

@nzthiago

This comment has been minimized.

Copy link
Member

commented May 23, 2018

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.).
@fabiocav

This comment has been minimized.

Copy link
Member

commented May 23, 2018

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?

@nzthiago

This comment has been minimized.

Copy link
Member

commented May 23, 2018

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:
#2554 (comment)

@fabiocav

This comment has been minimized.

Copy link
Member

commented May 23, 2018

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.

@nzthiago

This comment has been minimized.

Copy link
Member

commented May 25, 2018

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.

@brettsam

This comment has been minimized.

Copy link
Member

commented May 25, 2018

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

PR Azure/azure-webjobs-sdk-extensions#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: Azure/azure-webjobs-sdk#1726

@nzthiago

This comment has been minimized.

Copy link
Member

commented May 25, 2018

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

@brettsam

This comment has been minimized.

Copy link
Member

commented May 25, 2018

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.