I'm writing a queue-triggered azure function:
[FunctionName("OnTranslationEventQueueTriggered")]
public static void Run([QueueTrigger("translationsqueue", Connection = "TranslationsQueueConnectionString")]string myQueueItem, ILogger log)
{
log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");
}
The name of the queue is translationsqueue, but I'd like to be able to parameterize this.
How do we pull the name of the queue from configuration?
Based on the Binding expressions and patterns the app setting binding expression is wrapped in percent signs, see the following example:
in the class:
QueueTrigger("%translationsqueue%", …)
in the bindings:
{
"bindings": [
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "%translationsqueue%",
"connection": "TranslationsQueueConnectionString"
}
]
}
Related
I am new to Azure and tried my hands on azure blob storage trigger function.
I have created a function:
public static void Run(Stream myBlob, string name, Stream outputBlob, ILogger log)
{ log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
}
function.json file:
{
"bindings": [
{
"name": "myBlob",
"type": "blobTrigger",
"direction": "in",
"path": "hunaincontainer/{blobname}.{blobextension}.",
"connection": "hunainfunctionstorage1_STORAGE"
},
{
"type": "blob",
"name": "outputBlob",
"path": "hunaincontainer/{blobname}-ResizedImage.{blobextension}",
"connection": "hunainfunctionstorage1_STORAGE",
"direction": "out"
}
],
"disabled": false
}
hunaincontainer is a blob storage container in general purpose storage account. I am using free Azure for testing.
I run the function and it compiles successfully and then I upload an image to hunaincontainer using portal but it doesn't hit the function. Why? The connectionstring, key value and everything is set.
I think your issue is a stray period in the path you're setting! Instead of "path": "hunaincontainer/{blobname}.{blobextension}.", try "path": "hunaincontainer/{blobname}.{blobextension}"
I have a python function with a servicebus trigger and a blob input binding. The name of the blob match the content of the queue message.
My function.json file looks like that:
{
"bindings": [
{
"type": "serviceBusTrigger",
"name": "inputMessage",
"connection": "Omnibus_Validation_Listen_Servicebus",
"queueName": "validation-input-queue",
"accessRights": "listen",
"direction": "in"
},
{
"type": "blob",
"name": "inputBlob",
"path": "baselines/{inputMessage}",
"connection": "Omnibus_Blob_Storage",
"direction": "in"
}
],
"disabled": false
}
And it is working like a charm.
I'd to create a C# function with the same bindings but it does not seem to work.
I've used the same function.json file.
I have a project.json file:
{
"frameworks": {
"net46": {
"dependencies": {
"WindowsAzure.Storage": "8.5.0"
}
}
}
}
and my run.csx file looks like that:
public static void Run(string inputMessage, Stream inputBlob, TraceWriter log)
{
log.Info($"C# ServiceBus queue trigger function processed message: {inputMessage}");
}
When I save/run the function, I received this error:
Function ($import-baseline) Error: Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.import-baseline'. Microsoft.Azure.WebJobs.Host: No binding parameter exists for 'inputMessage'.
Is there any difference between the python and c# sdk for this kind of binding ?
I also can reproduce it on my side if I bind input blob path with baselines\{serviceBusTrigger} or baselines\{inputMessage} in the function.json file.
I am not sure whether it is supported to integrated input servicebus queue and input blob currently. We could give our feedback to Azure function team.
If Azure storage queue is acceptable we could use Azure storage queue trigger to do that. I test it on my side, it works correctly.
run.csx file
using System;
using System.Threading.Tasks;
public static void Run(string myQueueItem, Stream inputBlob, TraceWriter log)
{
log.Info($"C# storage queue trigger function processed message: {myQueueItem}");
StreamReader reader = new StreamReader(inputBlob);
string text = reader.ReadToEnd();
log.Info(text);
}
function.json
{
"bindings": [
{
"type": "blob",
"name": "inputBlob",
"path": "incontainer/{queueTrigger}",
"connection": "testweblog_STORAGE",
"direction": "in"
},
{
"type": "queueTrigger",
"name": "myQueueItem",
"queueName": "myqueue",
"connection": "testweblog_STORAGE",
"direction": "in"
}
],
"disabled": false
}
I have an Azure Function with Timer Trigger, and then I want to generate a file with dynamic (defined in runtime) name and contents and save it to e.g. OneDrive.
My function code:
public static void Run(TimerInfo myTimer, out string filename, out string content)
{
filename = $"{DateTime.Now}.txt";
content = $"Generated at {DateTime.Now} by Azure Functions";
}
And function.json:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
},
{
"type": "apiHubFile",
"name": "content",
"path": "{filename}",
"connection": "onedrive_ONEDRIVE",
"direction": "out"
}
],
"disabled": false
}
This fails though, with
Error indexing method 'Functions.TimerTriggerCSharp1'. Microsoft.Azure.WebJobs.Host:
Cannot bind parameter 'filename' to type String&. Make sure the parameter Type
is supported by the binding. If you're using binding extensions
(e.g. ServiceBus, Timers, etc.) make sure you've called the registration method
for the extension(s) in your startup code (e.g. config.UseServiceBus(),
config.UseTimers(), etc.).
Here is how you could do it:
#r "Microsoft.Azure.WebJobs.Extensions.ApiHub"
using System;
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host.Bindings.Runtime;
public static async Task Run(TimerInfo myTimer, TraceWriter log, Binder binder)
{
log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
var fileName = "mypath/" + DateTime.Now.ToString("yyyy-MM-ddThh-mm-ss") + ".txt";
var attributes = new Attribute[]
{
new ApiHubFileAttribute("onedrive_ONEDRIVE", fileName, FileAccess.Write)
};
var writer = await binder.BindAsync<TextWriter>(attributes);
var content = $"Generated at {DateTime.Now} by Azure Functions";
writer.Write(content);
}
And the function.json file:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "10 * * * * *"
},
{
"type": "apiHubFile",
"name": "outputFile",
"connection": "onedrive_ONEDRIVE",
"direction": "out"
}
],
"disabled": false
}
You shouldn't really need the apiHubFile declaration in your function.json but because of a bug I noticed today it should still be there. we will fix that bug.
To have full control over the name and path of an output during function execution, you need to use imperative binding
For example: function.json
{
"type": "blob",
"name": "outputBinder",
"path": "export/test",
"connection": "AzureWebJobsStorage",
"direction": "out"
},
Function:
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log, IBinder outputBinder)
{
var attribute new BlobAttribute($"{some dynamic path}/{some dynamic filename}", FileAccess.Write);
using (var stream = await outputBinder.BindAsync<Stream>(attribute))
{
// do whatever you want with this stream here...
}
}
Azure recently released a SaaS Table adapter for Azure functions. I know this feature is experimental with no documentation, but I'm trying to see if anyone has this working.
My bindings (function.json):
{
"bindings": [
{
"name": "data",
"type": "blobTrigger",
"direction": "in",
"path": "somePathToBlob",
"connection": "connectionName_STORAGE"
},
{
"type": "apiHubTable",
"name": "output",
"connection": "sql_SQL",
"direction": "out",
"tableName": "tblEventStage"
}
],
"disabled": false
}
Then in run.csx I have:
public static void Run(string data, ITable<EventRecord> output, TraceWriter log)
{
// add some records to the table
}
The function compiles successfully and then pops an alert message:
Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.ProcessAppInsights'. Microsoft.Azure.WebJobs.Extensions.ApiHub: The attribute ApiHubTableAttribute indicates a table binding. The parameter type must be one of the following: Microsoft.Azure.ApiHub.ITable, Microsoft.Azure.WebJobs.IAsyncCollector. To bind to a table client do not specify a table name. To bind to an entity specify the entity identifier.
What am I doing wrong?
Found the solution - I was using System.Data.Linq ITable instead of ITable from Microsoft.Azure.ApiHub. I removed System.Data.Linq and added nuget package Microsoft Azure ApiHub SDK. This requires adding a file package.json:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.Azure.ApiHub.Sdk": "0.6.10-alpha"
}
}
}
}
Records can be inserted to the table using:
output.CreateEntityAsync(record);
In my C# Azure Function I have a httpTrigger with this binding configuration:
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"methods": [
"post"
]
},
Inside the method I can do a req.Content.IsFormData() and True is returned. When I do a req.Content.ReadAsFormDataAsync(), nothing is returned. If I log the req.ToString(), the content has a zero length.
Where in the code (on Github.com) would be the best place to look for this answer? I could not find it. Thanks.
Here is the code, sorry for not posting it originally.
using System.Net;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log, ICollector<string> outputSbMsg)
{
var formdata = await req.Content.ReadAsFormDataAsync();
if (formdata.Count == 0)
{
log.Info("No Keys");
}
string message = $"Service Bus queue message created at: {DateTime.Now}";
log.Info(message);
outputSbMsg.Add(message);
return req.CreateResponse(HttpStatusCode.OK);
}