Bindings, Expressions, and Patterns
Azure Functions provides a powerful and flexible way to integrate with various services using bindings. Bindings simplify your code by separating the concerns of connecting to data and services from your function logic. To further enhance this flexibility, Functions supports binding expressions and patterns.
Binding Expressions
Binding expressions are placeholders in your function.json file or code that resolve to values from specific sources when your function executes. These expressions allow you to dynamically reference data from the incoming request, other bindings, or system properties.
Common Binding Expression Sources:
- Request Body: Access data from the HTTP request body. For example,
{requestBody}or{myInput.someProperty}if you have a JSON input binding. - Route Parameters: Access parameters defined in your route template. If your route is
/api/items/{id}, you can access{id}. - Query Parameters: Access parameters from the query string. For example,
{name}for a query parameter?name=World. - Headers: Access specific HTTP headers. For instance,
{myHeaderName}. - Other Bindings: Reference properties from other input or output bindings. If you have a Cosmos DB input binding named
myDoc, you can access its properties like{myDoc.id}. - System Properties: Access environment variables or system-provided information like
{sys.UtcNow}.
Example: HTTP Trigger with Dynamic Output Binding
Consider an HTTP-triggered function that writes a message to a storage queue based on a query parameter.
function.json:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get"
],
"route": "greet/{name}"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "queue",
"direction": "out",
"name": "outputQueue",
"queueName": "greetings",
"connection": "AzureWebJobsStorage"
}
]
}
C# Code:
using System.Net;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.Functions.Worker;
public static class GreetFunction
{
[Function("GreetFunction")]
public static async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "greet/{name}")] HttpRequestData req,
string name,
[Queue("greetings", Connection = "AzureWebJobsStorage")] out string outputQueue)
{
outputQueue = $"Hello, {name}!";
var response = req.CreateResponse(HttpStatusCode.OK);
response.WriteString($"Greeting sent to queue: {outputQueue}");
return response;
}
}
In this example:
{name}in therouteparameter of the HTTP trigger is directly mapped to thestring nameparameter in the C# function.- The string
$"Hello, {name}!"is assigned to theoutputQueue, which is an out binding to a storage queue named "greetings". The value ofnamefrom the URL is dynamically included in the message sent to the queue.
Binding Patterns
Binding patterns extend the concept of binding expressions by allowing you to define more complex data structures and use them within your bindings, particularly with collections or structured data.
Common Binding Patterns:
- Array/Collection Binding: When you expect multiple items from a binding, you can use an array or a collection type in your function signature. Azure Functions will automatically deserialize the incoming data into your collection.
- Object/Class Binding: For structured data (like JSON), you can define a C# class (or equivalent in other languages) that mirrors the structure and use it as a binding type.
- Wildcard Binding: In some scenarios, you might use wildcards (e.g.,
*) in binding configurations, especially for input bindings that retrieve multiple items.
Example: Processing Multiple Blobs
Imagine a function triggered by a blob container that processes all new blob files added.
function.json:
{
"bindings": [
{
"name": "blobs",
"type": "blobTrigger",
"direction": "in",
"path": "samples-workitems/{name}",
"connection": "AzureWebJobsStorage"
},
{
"name": "inputBlob",
"type": "blob",
"direction": "in",
"path": "samples-workitems/{name}",
"connection": "AzureWebJobsStorage"
},
{
"type": "blob",
"direction": "out",
"name": "outputBlob",
"path": "processed-workitems/{name}",
"connection": "AzureWebJobsStorage"
}
]
}
C# Code:
using System.IO;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
public static class BlobProcessor
{
[Function("BlobProcessor")]
public static void Run(
[BlobTrigger("samples-workitems/{name}")] Stream myBlob,
string name,
[Blob("processed-workitems/{name}")] out Stream outputBlob,
ILogger log)
{
log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
// Example: Read from input blob and write to output blob
// In a real scenario, you'd perform transformations
outputBlob = myBlob; // Simple pass-through for demonstration
outputBlob.SetLength(myBlob.Length); // Ensure output stream has correct length
}
}
Here:
{name}is used in thepathfor both the trigger and the input/output bindings. This ensures that the same blob that triggered the function is read and written to.- The
blobTriggerreceives aStreamrepresenting the content of the blob. - The
namevariable captures the blob's filename. - The
outputBlobis configured to write to a different container, using the same{name}pattern to maintain the filename.
Key Takeaways
- Binding Expressions enable dynamic data referencing.
- Binding Patterns help manage structured or multiple data items.
- Use expressions like
{paramName},{sys.UtcNow}, etc. - Leverage language features (arrays, classes) to work with patterns.
- Refer to the official Azure Functions documentation for a complete list of available binding expressions and advanced patterns.