3 min read
Azure Functions Input/Output Bindings: Declarative Data Access
Bindings eliminate boilerplate. Declare your data sources and destinations—Azure Functions handles the connections.
Binding Types
- Trigger: What starts the function
- Input: Data to read
- Output: Where to write results
Cosmos DB Bindings
// Input binding - read document
[FunctionName("GetOrder")]
public static IActionResult GetOrder(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req,
[CosmosDB(
databaseName: "orders-db",
containerName: "orders",
Connection = "CosmosDBConnection",
Id = "{Query.orderId}",
PartitionKey = "{Query.customerId}"
)] Order order)
{
return new OkObjectResult(order);
}
// Output binding - write document
[FunctionName("CreateOrder")]
public static IActionResult CreateOrder(
[HttpTrigger(AuthorizationLevel.Function, "post")] Order order,
[CosmosDB(
databaseName: "orders-db",
containerName: "orders",
Connection = "CosmosDBConnection"
)] out dynamic document)
{
document = order;
return new OkObjectResult(order);
}
Blob Storage Bindings
// Trigger on blob + output to another container
[FunctionName("ProcessImage")]
public static void ProcessImage(
[BlobTrigger("uploads/{name}", Connection = "StorageConnection")] Stream inputBlob,
[Blob("processed/{name}", FileAccess.Write, Connection = "StorageConnection")] Stream outputBlob,
string name,
ILogger log)
{
log.LogInformation($"Processing blob: {name}");
// Process and write to output
inputBlob.CopyTo(outputBlob);
}
Queue Bindings
// Queue trigger with output to another queue
[FunctionName("ProcessMessage")]
public static void ProcessMessage(
[QueueTrigger("input-queue", Connection = "StorageConnection")] string message,
[Queue("output-queue", Connection = "StorageConnection")] out string outputMessage,
ILogger log)
{
outputMessage = $"Processed: {message}";
}
// Multiple output messages
[FunctionName("FanOut")]
public static void FanOut(
[QueueTrigger("input-queue")] string message,
[Queue("output-queue")] ICollector<string> outputMessages)
{
for (int i = 0; i < 10; i++)
{
outputMessages.Add($"Message {i}: {message}");
}
}
Table Storage Bindings
// Read from Table Storage
[FunctionName("GetEntity")]
public static IActionResult GetEntity(
[HttpTrigger] HttpRequest req,
[Table("customers", "{Query.partitionKey}", "{Query.rowKey}")] Customer customer)
{
return new OkObjectResult(customer);
}
// Write to Table Storage
[FunctionName("SaveEntity")]
public static IActionResult SaveEntity(
[HttpTrigger] Customer customer,
[Table("customers")] out Customer tableEntity)
{
tableEntity = customer;
tableEntity.PartitionKey = customer.Region;
tableEntity.RowKey = customer.Id;
return new OkResult();
}
Service Bus Bindings
[FunctionName("ProcessServiceBus")]
public static async Task ProcessServiceBus(
[ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")] string message,
[ServiceBus("output-topic", Connection = "ServiceBusConnection")] IAsyncCollector<string> outputMessages,
ILogger log)
{
await outputMessages.AddAsync($"Processed: {message}");
}
SignalR Bindings
// Negotiate endpoint for SignalR clients
[FunctionName("negotiate")]
public static SignalRConnectionInfo Negotiate(
[HttpTrigger] HttpRequest req,
[SignalRConnectionInfo(HubName = "chat")] SignalRConnectionInfo connectionInfo)
{
return connectionInfo;
}
// Send messages to SignalR hub
[FunctionName("broadcast")]
public static async Task Broadcast(
[HttpTrigger] dynamic message,
[SignalR(HubName = "chat")] IAsyncCollector<SignalRMessage> signalRMessages)
{
await signalRMessages.AddAsync(new SignalRMessage
{
Target = "newMessage",
Arguments = new[] { message }
});
}
Binding Expressions
// Use trigger data in binding expressions
[FunctionName("DynamicBinding")]
public static void DynamicBinding(
[QueueTrigger("orders")] Order order,
[Blob("receipts/{OrderId}.json")] out string receipt) // {OrderId} from trigger
{
receipt = JsonConvert.SerializeObject(order);
}
Bindings let you focus on business logic, not plumbing.