Desired Scenario
From an Arduino:
- take a photo and upload image as a blob in Azure storage container (works fine)
- call a Web Function using HTTP with blob name and other info (works fine) From the Web function
- read the HTTP request (works fine)
- read the blob using the information from the HTTP request (does not work)
- process the blob (not implemented yet)
- respond result to Arduino
Problem
I can't figure out how to make the binding from the path to the HTTP parameters.
Web Function Config
{
"bindings": [
{
"authLevel": "function",
"name": "request",
"type": "httpTrigger",
"direction": "in",
"methods": [
"post"
]
},
{
"name": "$return",
"type": "http",
"direction": "out"
}
],
"disabled": false
}
Error:
Function ($HttpTriggerCSharp1) Error: Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.HttpTriggerCSharp1'. Microsoft.Azure.WebJobs.Host: No binding parameter exists for 'blobName'.
ORIGINAL, NON-WORKING code (working code below):
using System.Net;
public static async Task<HttpResponseMessage> Run(
HttpRequestMessage request,
string blobName, // DOES NOT WORK but my best guess so far
string inputBlob,
TraceWriter log)
{
// parse query parameter
string msgType = request.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "msgType", true) == 0)
.Value;
// Get request body
dynamic data = await request.Content.ReadAsAsync<object>();
// Set name to query string or body data
msgType = msgType ?? data?.msgType;
string deviceId = data.deviceId;
string blobName = data.BlobName; // DOES NOT COMPILE
log.Info("blobName=" + blobName); // DOES NOT WORK
log.Info("msgType=" + msgType);
log.Info("data=" + data);
return msgType == null
? request.CreateResponse(HttpStatusCode.BadRequest, "HTTP parameter must contain msgType=<type> on the query string or in the request body")
: request.CreateResponse(HttpStatusCode.OK, "Hello " + deviceId + " inputBlob:");// + inputBlob );
}
HTTP request looks like this:
https://xxxxxxprocessimagea.azurewebsites.net/api/HttpTriggerCSharp1?code=CjsO/EzhtUBMgRosqxxxxxxxxxxxxxxxxxxxxxxx0tBBqaiXNewn5A==&msgType=New image
"deviceId": "ArduinoD1_001",
"msgType": "New image",
"MessageId": "12345",
"UTC": "2017-01-08T10:45:09",
"FullBlobName": "/xxxxxxcontainer/ArduinoD1_001/test.jpg",
"BlobName": "test.jpg",
"BlobSize": 9567,
"WiFiconnects": 1,
"ESPmemory": 7824,
"Counter": 1
(I know, msgType appears both in URL and in headers. I've tried different combinations - no effect).
If what I'm trying to do is impossible, alternative suggestions are also welcome. I just need a way through.
This code works thanks to Tom Sun's hint. The trick was to remove the binding to the storage blob in the JSON and instead just call the blob directly from the code.
#r "Microsoft.WindowsAzure.Storage"
using Microsoft.WindowsAzure.Storage; // Namespace for CloudStorageAccount
using Microsoft.WindowsAzure.Storage.Blob; // Namespace for Blob storage types
using Microsoft.WindowsAzure.Storage.Queue;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using System.Net;
using System.IO;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage request, string inputBlob, TraceWriter log)
{
string msgType = request.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "msgType", true) == 0)
.Value;
dynamic data = await request.Content.ReadAsAsync<object>();
msgType = msgType ?? data?.msgType;
string deviceId = data.deviceId;
string blobName = data.BlobName;
string connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.Storage);
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("nnriothubcontainer/" + deviceId);
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
MemoryStream imageData = new MemoryStream();
await blob.DownloadToStreamAsync(imageData);
return msgType == null
? request.CreateResponse(HttpStatusCode.BadRequest, "HTTP parameter must contain msgType=<type> on the query string or in the request body")
: request.CreateResponse(HttpStatusCode.OK, "Hello " + deviceId + " inputBlob size:" + imageData.Length);// + inputBlob );
}