Azure / Azure/azure-functions-host
BlobTrigger payload expression binding not working as expected
- Dominant language
- C#
- Stars
- 2k
- Forks
- 482
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 38
Description
When using a queue trigger binding with a blob input binding, the following example works as expected. In this example, we are able to parse the payload of `myBook` and use the `id` to evaluate `input-container/{id}.txt` to `input-container/1.txt`
QueueTrigger/index.js
```typescript
import { AzureFunction, Context } from "@azure/functions"
const queueTrigger:
AzureFunction = async function (context: Context, myBook: Book): Promise
{
context.log("Queue trigger function processed blob");
context.log("Book name:", myBook.name);
context.log("Book content:", context.bindings.myBlob);
};
type Book = {
id: string,
name: string,
}
export default queueTrigger;
```
function.json
```json
{
"bindings": [
{
"name": "myBook",
"type": "queueTrigger",
"direction": "in",
"queueName": "book-trigger",
"connection": "AzureWebJobsStorage"
},
{
"name": "myBlob",
"type": "blob",
"direction": "in",
"path": "input-container/{id}.txt",
"connection": "AzureWebJobsStorage"
}
],
"scriptFile": "../dist/QueueTrigger/index.js"
}
```
Trigger payload:
`{ "id": "1", "name": "mybook" }`
Output:
```log
[2022-10-25T22:58:17.636Z] Executing 'Functions.QueueTrigger' (Reason='New queue message detected on 'book-trigger'.', Id=e4545b2a-0fe5-4f08-aed5-705f24dfc2a3)
[2022-10-25T22:58:17.637Z] Trigger Details: MessageId: fd82d6a8-40dd-4275-a700-51c394e5bc1c, DequeueCount: 1, InsertedOn: 2022-10-25T22:58:15.000+00:00
[2022-10-25T22:58:17.857Z] Queue trigger function processed blob
[2022-10-25T22:58:17.858Z] Book name: mybook
[2022-10-25T22:58:17.858Z] Book content: hello world
[2022-10-25T22:58:17.884Z] Executed 'Functions.QueueTrigger' (Succeeded, Id=e4545b2a-0fe5-4f08-aed5-705f24dfc2a3, Duration=270ms)
```
**This behaviour is also expected to work for the BlobTrigger**
BlobTrigger/index.js
```typescript
import { AzureFunction, Context } from "@azure/functions"
const blobTrigger:
AzureFunction = async function (context: Context, myBook: Book): Promise
{
context.log("Blob trigger function processed blob")
context.log("Book name:", myBook.name);
context.log("Book content:", context.bindings.myBlob);
};
type Book = {
id: string,
name: string,
}
export default blobTrigger;
```
function.json
```json
{
"bindings": [
{
"name": "myBook",
"type": "blobTrigger",
"direction": "in",
"path": "book-trigger",
"connection": "AzureWebJobsStorage",
"dataType": "string"
},
{
"name": "myBlob",
"type": "blob",
"direction": "in",
"path": "input-container/{id}.txt",
"connection": "AzureWebJobsStorage",
"dataType": "string"
}
],
"scriptFile": "../dist/BlobTrigger/index.js"
}
```
Trigger payload (book.json)
`{ "id": "1", "name": "mybook" }`
Output
```log
[2022-10-25T22:58:52.738Z] Executing 'Functions.BlobTrigger' (Reason='New blob detected(LogsAndContainerScan): book-trigger/book.json', Id=a8c7a83f-f490-43a1-a6ca-955f554c19b5)
[2022-10-25T22:58:52.738Z] Trigger Details: MessageId: 3a6ad397-27ca-47d3-b012-5973cd36a039, DequeueCount: 1, InsertedOn: 2022-10-25T22:58:52.000+00:00, BlobCreated: 2022-10-25T21:39:49.000+00:00, BlobLastModified: 2022-10-25T22:58:42.000+00:00
[2022-10-25T22:58:52.785Z] Executed 'Functions.BlobTrigger' (Failed, Id=a8c7a83f-f490-43a1-a6ca-955f554c19b5, Duration=116ms)
[2022-10-25T22:58:52.785Z] System.Private.CoreLib: Exception while executing function: Functions.BlobTrigger. Microsoft.Azure.WebJobs.Host: No value for named parameter 'id'.
```
We should have seen is a similar result to what happened with the queue trigger:
```
Book name: mybook
Book content: hello world
```
Interestingly, when we remove the use of the blob input binding and just use a blob trigger by itself, still binding to a `Book`, instead of getting the payload as a `Book`, we get binary data (even if the data type is set to string):
```json
{
"bindings": [
{
"name": "myBook",
"type": "blobTrigger",
"direction": "in",
"path": "book-trigger",
"connection": "AzureWebJobsStorage",
"dataType": "string"
}
],
"scriptFile": "../dist/BlobTrigger/index.js"
}
```
```log
[2022-10-25T23:01:19.747Z] Executing 'Functions.BlobTrigger' (Reason='New blob detected(LogsAndContainerScan): book-trigger/book.json', Id=75277b64-3197-477c-afeb-044a30253ce6)
[2022-10-25T23:01:19.748Z] Trigger Details: MessageId: 9bd797ac-a7d8-477e-8516-791ae788c6c2, DequeueCount: 1, InsertedOn: 2022-10-25T23:01:19.000+00:00, BlobCreated: 2022-10-25T21:39:49.000+00:00, BlobLastModified: 2022-10-25T23:01:11.000+00:00
[2022-10-25T23:01:19.821Z] Blob trigger function processed blob
[2022-10-25T23:01:19.821Z] MyBook:
[2022-10-25T23:01:19.821Z] Book name: undefined
[2022-10-25T23:01:19.849Z] Executed 'Functions.BlobTrigger' (Succeeded, Id=75277b64-3197-477c-afeb-044a30253ce6, Duration=205ms)
```
We would expect to get a POCO as we have logic in the host [here](https://github.com/Azure/azure-functions-host/blob/91e0d11a13ee25debad1b5623088543c38a7d40d/src/WebJobs.Script/Description/Workers/WorkerFunctionInvoker.cs#L186) that pulls json values from the payload if it's a String. We can see this in action with the queue trigger example.
- [ ] The goal of this issue is to investigate why the payload binding expression is not working for the BlobTrigger
Contributor guide
Research direction
Start with src/WebJobs.Script/Description/Workers/WorkerFunctionInvoker.cs at the referenced payload-binding logic, then compare the queue-trigger and BlobTrigger examples and their function.json bindings. Done means explaining and correcting why BlobTrigger payload values are unavailable to the input binding expression and why the trigger payload is received as binary data instead of the expected Book object.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, csharp, typescript
- Domain
- backend, cloud
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100