Azure Functions Input & Output Bindings
Connecting to Azure Services Without SDK Code
Introduction
Azure Functions bindings provide a declarative way to connect your function code to external services without writing boilerplate SDK code. By simply adding attributes to your function parameters, you can read from or write to Azure Storage, Service Bus, Cosmos DB, and many other services.
This comprehensive guide covers:
- Input bindings — Reading data from external sources
- Output bindings — Writing data to external destinations
- Multiple bindings — Using multiple bindings in one function
- Custom bindings — Creating your own bindings
- Best practices — Efficient and secure binding usage
Understanding Bindings
How Bindings Work
┌─────────────────────────────────────────────────────────────────────┐
│ BINDING ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ AZURE FUNCTION │ │
│ │ │ │
│ │ [Blob("data/{name}")] ← INPUT BINDING │ │
│ │ │ │ │
│ │ │ Function Logic │ │
│ │ ▼ │ │
│ │ [Queue("output")] ← OUTPUT BINDING │ │
│ │ │ │
│ └────────────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ BINDING CONTAINER │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Blob │ │ Queue │ │ CosmosDB │ │ │
│ │ │ Storage │ │ Service │ │ │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
Binding Types
| Type | Description | Examples |
|---|---|---|
| Trigger | Starts function execution | Queue message, HTTP request, Timer |
| Input | Reads data into function | Blob content, Table entity, Cosmos DB document |
| Output | Writes data from function | Blob storage, Queue message, HTTP response |
Input Bindings
Blob Storage Input
[FunctionName("ReadBlob")]
public async Task<string> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req,
[Blob("containers/{name}")] BlobClient blob)
{
var content = await blob.DownloadContentAsync();
return content.Value.Content.ToString();
}
Table Storage Input
[FunctionName("GetOrder")]
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req,
[Table("orders", "2024-01", "order-123")] OrderEntity order)
{
return new OkObjectResult(order);
}
Cosmos DB Input
[FunctionName("GetDocument")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req,
[CosmosDB("database", "collection",
Id = "{id}",
PartitionKey = "{partition}")]
MyDocument document)
{
return document == null
? new NotFoundResult()
: new OkObjectResult(document);
}
Multiple Input Bindings
[FunctionName("ProcessData")]
public async Task Run(
[QueueTrigger("orders")] OrderMessage order,
[Blob("archive")] BlobContainerClient archiveContainer,
[Table("orders")] TableClient tableClient)
{
// Use both bindings
await archiveContainer.CreateIfNotExistsAsync();
await tableClient.CreateIfNotExistsAsync();
}
Output Bindings
Blob Storage Output
[FunctionName("WriteBlob")]
public async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
[Blob("output/{DateTime.UtcNow:yyyy-MM-dd}/result.txt", FileAccess.Write)] Stream output)
{
await req.Body.CopyToAsync(output);
}
Queue Output
[FunctionName("ProcessAndQueue")]
public async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
[Queue("processed-orders")] IAsyncCollector<string> queueCollector)
{
var order = await req.Body.ReadAsStringAsync();
await queueCollector.AddAsync(order);
}
Table Storage Output
[FunctionName("SaveToTable")]
[return: Table("orders")]
public OrderEntity CreateOrder(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
{
var order = new OrderEntity
{
PartitionKey = DateTime.UtcNow.ToString("yyyy-MM"),
RowKey = Guid.NewGuid().ToString(),
CustomerName = "John Doe",
Total = 99.99
};
return order;
}
Cosmos DB Output
[FunctionName("CreateDocument")]
[return: CosmosDB("database", "collection")]
public MyDocument CreateDoc(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
{
return new MyDocument
{
Id = Guid.NewGuid().ToString(),
Data = "Sample data"
};
}
HTTP Response Output
[FunctionName("GetResponse")]
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req)
{
return new OkObjectResult(new { status = "success" });
}
Multiple Bindings Example
Complete Function with Multiple Bindings
[FunctionName("ProcessOrderWorkflow")]
public async Task Run(
// Trigger
[ServiceBusTrigger("orders", Connection = "ServiceBusConnection")]
ServiceBusReceivedMessage message,
// Output - Archive to blob
[Blob("archive/orders/{DateTime.UtcNow:yyyy-MM-dd}", FileAccess.Write, Connection = "StorageConnection")]
Stream archiveStream,
// Output - Dead letter queue
[Queue("deadletter", Connection = "StorageConnection")]
IAsyncCollector<ServiceBusMessage> deadLetterQueue,
// Output - Results table
[Table("results", Connection = "StorageConnection")]
TableClient resultsTable,
ILogger log)
{
log.LogInformation("Processing order...");
try
{
var order = JsonSerializer.Deserialize<Order>(message.Body);
// Process the order (business logic)
var result = await ProcessOrderAsync(order);
// Write to archive
await archiveStream.WriteAsync(message.Body);
// Add to results table
await resultsTable.AddEntityAsync(new TableEntity
{
RowKey = order.OrderId,
PartitionKey = DateTime.UtcNow.ToString("yyyy-MM-dd"),
["Status"] = "Processed",
["Result"] = JsonSerializer.Serialize(result)
});
log.LogInformation("Order processed successfully");
}
catch (Exception ex)
{
log.LogError(ex, "Failed to process order");
// Send to dead letter
var deadLetter = new ServiceBusMessage(message.Body);
deadLetter.ApplicationProperties["Error"] = ex.Message;
await deadLetterQueue.AddAsync(deadLetter);
}
}
Binding Expressions
Using Query Parameters
[FunctionName("GetFile")]
public async Task<string> Run(
[HttpTrigger("get", Route = "files/{filename}")] HttpRequest req,
[Blob("documents/{filename}")] string content)
{
return content;
}
Using Headers
[FunctionName("GetByHeader")]
public async Task<IActionResult> Run(
[HttpTrigger("get")] HttpRequest req,
[Blob("documents", Connection = "Storage")] BlobContainerClient container,
ILogger log)
{
var filename = req.Headers["X-Filename"];
var blob = container.GetBlobClient(filename);
var content = await blob.DownloadContentAsync();
return new OkObjectResult(content.Value.Content);
}
Using System Properties
[FunctionName("SystemProperties")]
public void Run(
[QueueTrigger("orders", Connection = "QueueConnection")] string message,
[Blob("audit", FileAccess.Write)] Stream auditLog,
ExecutionContext context,
ILogger log)
{
// Access system properties
log.LogInformation($"Function directory: {context.FunctionDirectory}");
log.LogInformation($"Function name: {context.FunctionName}");
log.LogInformation($"Invocation ID: {context.InvocationId}");
}
Configuration
Local Settings (local.settings.json)
{
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"ServiceBusConnection": "Endpoint=sb://...",
"StorageConnection": "DefaultEndpointsProtocol=https;AccountName=..."
}
}
Application Settings in Azure
# Set connection strings
az functionapp config appsettings set \
--name my-function-app \
--resource-group my-rg \
--settings "StorageConnection=@Microsoft.KeyVault(...)"
Best Practices
| Practice | Description |
|---|---|
| Use binding expressions | Keep URLs and parameters flexible |
| Handle missing data | Check for null in input bindings |
| Connection pooling | Use singleton clients where possible |
| Error handling | Use try/catch for all binding operations |
| Logging | Log binding operations for debugging |
Performance Tips
// Good: Use BlobClient for multiple operations
[Blob("container/{name}")] BlobClient blob
// Better: Read directly for single reads
[Blob("container/file.txt")] string content
Related Topics
- Triggers — All available trigger types
- Error Handling — Handling binding errors
- Managed Identity — Secure authentication
Azure Integration Hub - Intermediate Level