I need to bind to an output blob, but the blob path needs to be computed dynamically in my function. How do I do it?
Binder
is an advanced binding technique that allows you to perform bindings imperatively in your code as opposed to declaratively via the function.json
metadata file. You might need to do this in cases where the computation of binding path or other inputs needs to happen at runtime in your function. Note that when using an Binder
parameter, you should not include a corresponding entry in function.json
for that parameter.
In the below example, we're dynamically binding to a blob output. As you can see, because you're declaring the binding in code, your path info can be computed in any way you wish. Note that you can bind to any of the other raw binding attributes as well (e.g. QueueAttribute
/EventHubAttribute
/ServiceBusAttribute
/etc.) You can also do so iteratively to bind multiple times.
Note that the type parameter passed to BindAsync
(in this case TextWriter
) must be a type that the target binding supports.
using System;
using System.Net;
using Microsoft.Azure.WebJobs;
public static async Task<HttpResponseMessage> Run(
HttpRequestMessage req, Binder binder, TraceWriter log)
{
log.Verbose($"C# HTTP function processed RequestUri={req.RequestUri}");
// determine the path at runtime in any way you choose
string path = "samples-output/path";
using (var writer = await binder.BindAsync<TextWriter>(new BlobAttribute(path)))
{
writer.Write("Hello World!!");
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
And here is the corresponding metadata:
{
"bindings": [
{
"name": "req",
"type": "httpTrigger",
"direction": "in"
},
{
"name": "res",
"type": "http",
"direction": "out"
}
]
}
There are bind overloads that take an array of attributes. In cases where you need to control the target storage account, you pass in a collection of attributes, starting with the binding type attribute (e.g. BlobAttribute
) and inlcuding a StorageAccountAttribute
instance pointing to the account to use. For example:
var attributes = new Attribute[]
{
new BlobAttribute(path),
new StorageAccountAttribute("MyStorageAccount")
};
using (var writer = await binder.BindAsync<TextWriter>(attributes))
{
writer.Write("Hello World!");
}
Have consolidated all of the information from this an other posts along with comments and created a blog post that demonstrates how to use Binder with a real world scenario. Thanks to @mathewc this became possible.