Azure Functions — All Trigger Types
Responding to Events from Azure Services
Introduction
Azure Functions are event-driven, meaning they execute in response to various triggers from Azure services and external sources. Understanding the different trigger types is essential for building serverless applications that respond to the right events at the right time.
This comprehensive guide covers:
- Trigger overview — Complete list of available triggers
- Implementation details — Code examples for each trigger type
- Configuration options — How to configure triggers
- Use cases — When to use each trigger type
- Best practices — Optimizing trigger usage
Trigger Overview
Available Triggers
| Trigger | Service | Use Case | Processing Mode |
|---|---|---|---|
| HTTP | Built-in | Web APIs, webhooks | Synchronous |
| Timer | Built-in | Scheduled jobs | Time-based |
| Blob Storage | Azure Storage | File processing | Event-driven |
| Queue Storage | Azure Storage | Message processing | Polling |
| Service Bus | Service Bus | Enterprise messaging | Polling |
| Event Grid | Event Grid | Event routing | Push |
| Event Hubs | Event Hubs | High-throughput streaming | Polling |
| Cosmos DB | Cosmos DB | NoSQL change feed | Polling |
| SendGrid | SendGrid | Email events | Push |
| Twilio | Twilio | SMS/webhook events | Push |
| Webhook | External | External triggers | Push |
HTTP Trigger
Web API Endpoint
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
public class OrderFunctions
{
[FunctionName("GetOrders")]
public IActionResult GetOrders(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
var orders = new[] { new { Id = 1 }, new { Id = 2 } };
return new OkObjectResult(orders);
}
[FunctionName("CreateOrder")]
public async Task<IActionResult> CreateOrder(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
return new CreatedResult($"/orders/123", new { status = "created" });
}
}
Webhook Handler
[FunctionName("GitHubWebhook")]
public async Task<IActionResult> GitHubWebhook(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req)
{
string signature = req.Headers["X-Hub-Signature-256"];
string body = await req.ReadAsStringAsync();
// Verify webhook signature
if (!VerifySignature(signature, body))
return new UnauthorizedResult();
var payload = JsonSerializer.Deserialize<GitHubPayload>(body);
if (payload.Action == "opened")
{
// Process the event
}
return new OkResult();
}
Authorization Levels
// Anonymous - no auth required
[HttpTrigger(AuthorizationLevel.Anonymous, "get")]
// Function - requires function key
[HttpTrigger(AuthorizationLevel.Function, "get")]
// Admin - requires admin key
[HttpTrigger(AuthorizationLevel.Admin, "get")]
// Custom - use specific key
[HttpTrigger(AuthorizationLevel.Function, "get", Name = "MyFunction")]
Timer Trigger
Scheduled Job
[FunctionName("DailyReport")]
public void Run([TimerTrigger("0 0 8 * * *")] TimerInfo myTimer)
{
Console.WriteLine($"Report job executed at: {DateTime.Now}");
Console.WriteFunction($"Next run: {myTimer.Next}");
// Run daily tasks
GenerateReport();
}
CRON Expressions
┌─────────────────┬─────────────────────────────────────┐
│ Expression │ Description │
├─────────────────┼─────────────────────────────────────┤
│ 0 0 * * * * │ Every day at midnight │
│ 0 */15 * * * * │ Every 15 minutes │
│ 0 0 * * 1-5 │ Weekdays at midnight │
│ 0 0 1 * * │ First day of every month │
│ 0 0 8 * * 1-5 │ Weekdays at 8 AM │
│ 0 */30 * * * * │ Every 30 minutes │
└─────────────────┴─────────────────────────────────────┘
Timer with Configuration
[FunctionName("ScheduledCleanup")]
public async Task Run(
[TimerTrigger("%CleanupSchedule%")] TimerInfo timer,
ILogger log)
{
// Schedule comes from configuration
log.LogInformation($"Cleanup running at: {DateTime.Now}");
// Long-running task with timeout
var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
await CleanupOldDataAsync(cts.Token);
}
Blob Storage Trigger
File Processing
[FunctionName("ProcessUploadedFile")]
public async Task ProcessUploadedFile(
[BlobTrigger("uploads/{name}")] Stream fileStream,
string name,
ILogger log)
{
log.LogInformation($"Processing file: {name}");
using var reader = new StreamReader(fileStream);
var content = await reader.ReadToEndAsync();
// Process based on file type
if (name.EndsWith(".csv"))
await ProcessCsvAsync(content);
else if (name.EndsWith(".json"))
await ProcessJsonAsync(content);
}
Blob Metadata Access
[FunctionName("ProcessWithMetadata")]
public async Task Run(
[BlobTrigger("uploads/{name}")] BlobClient blob,
string name,
ILogger log)
{
// Get blob properties
var properties = await blob.GetPropertiesAsync();
log.LogInformation($"Size: {properties.Value.ContentLength}");
log.LogInformation($"ContentType: {properties.Value.ContentType}");
log.LogInformation($"Created: {properties.Value.CreatedOn}");
}
Queue Storage Trigger
Message Processing
[FunctionName("ProcessQueueMessage")]
public void ProcessQueueMessage(
[QueueTrigger("orders")] string message,
ILogger log)
{
log.LogInformation($"Processing: {message}");
var order = JsonSerializer.Deserialize<Order>(message);
ProcessOrder(order);
}
POCO Message Types
public class OrderMessage
{
public string OrderId { get; set; }
public string CustomerId { get; set; }
public decimal Total { get; set; }
}
[FunctionName("ProcessOrderMessage")]
public void ProcessOrderMessage(
[QueueTrigger("orders")] OrderMessage message,
ILogger log)
{
log.LogInformation($"Processing order: {message.OrderId}");
// Direct access to properties
}
Service Bus Trigger
Queue Processing
[FunctionName("ProcessServiceBusMessage")]
public void ProcessServiceBusMessage(
[ServiceBusTrigger("orders", Connection = "ServiceBusConnection")]
ServiceBusReceivedMessage message,
ILogger log)
{
var body = message.Body.ToString();
log.LogInformation($"Received: {body}");
var order = JsonSerializer.Deserialize<Order>(body);
await ProcessOrderAsync(order);
}
Topic Subscription
[FunctionName("ProcessTopicMessage")]
public void ProcessTopicMessage(
[ServiceBusTrigger("orders-topic", "email-subscription", Connection = "ServiceBusConnection")]
ServiceBusReceivedMessage message,
ILogger log)
{
log.LogInformation($"Subject: {message.Subject}");
log.LogInformation($"MessageId: {message.MessageId}");
await SendEmailAsync(message);
}
Event Grid Trigger
Event Handler
[FunctionName("HandleBlobEvent")]
public void HandleBlobEvent(
[EventGridTrigger] EventGridEvent eventGridEvent,
ILogger log)
{
log.LogInformation($"Event Type: {eventGridEvent.EventType}");
log.LogInformation($"Subject: {eventGridEvent.Subject}");
var data = eventGridEvent.Data;
log.LogInformation($"Blob URL: {data["url"]}");
if (eventGridEvent.EventType == "Microsoft.Storage.BlobCreated")
{
await ProcessNewBlobAsync(data["url"].ToString());
}
}
CloudEvent Format
[FunctionName("HandleCloudEvent")]
public async Task HandleCloudEvent(
[EventGridTrigger] CloudEvent cloudEvent,
ILogger log)
{
log.LogInformation($"Type: {cloudEvent.Type}");
log.LogInformation($"Source: {cloudEvent.Source}");
var data = JsonSerializer.Deserialize<MyEventData>(cloudEvent.Data.ToString());
await ProcessEventAsync(data);
}
Event Hubs Trigger
Stream Processing
[FunctionName("ProcessEventHubEvents")]
public async Task ProcessEventHubEvents(
[EventHubTrigger("telemetry", Connection = "EventHubConnection")]
EventData[] events,
ILogger log)
{
log.LogInformation($"Processing {events.Length} events");
foreach (var eventData in events)
{
var body = Encoding.UTF8.GetString(eventData.Body);
var telemetry = JsonSerializer.Deserialize<Telemetry>(body);
await ProcessTelemetryAsync(telemetry);
}
}
Batch Processing
[FunctionName("ProcessEventsBatch")]
public async Task ProcessEventsBatch(
[EventHubTrigger("orders", Connection = "EventHubConnection",
ConsumerGroup = "processor")]
string[] messages,
ILogger log)
{
foreach (var message in messages)
{
var order = JsonSerializer.Deserialize<Order>(message);
await ProcessOrderAsync(order);
}
}
Cosmos DB Trigger
Change Feed Processing
[FunctionName("ProcessCosmosChanges")]
public async Task ProcessCosmosChanges(
[CosmosDBTrigger(
databaseName: "ordersdb",
collectionName: "orders",
Connection = "CosmosConnection",
LeaseCollectionName = "leases")]
IReadOnlyList<Document> documents)
{
foreach (var doc in documents)
{
var changeType = doc.GetPropertyValue<string>("operationType");
if (changeType == "create")
{
await HandleOrderCreatedAsync(doc);
}
else if (changeType == "replace")
{
await HandleOrderUpdatedAsync(doc);
}
}
}
Binding Parameters
Connection Configuration
[FunctionName("WithConnections")]
public void Run(
[BlobTrigger("container/{name}")] Stream blob,
[QueueTrigger("myqueue")] string message,
[ServiceBusTrigger("queue")] ServiceBusMessage sbMessage,
ILogger log)
{
// Each trigger can have its own connection
// Configure in local.settings.json or app settings
}
Configuration in local.settings.json
{
"Values": {
"AzureWebJobsStorage": "DefaultEndpointsProtocol=...",
"ServiceBusConnection": "Endpoint=sb://...",
"EventHubConnection": "Endpoint=sb://...",
"CosmosConnection": "AccountEndpoint=..."
}
}
Best Practices
| Practice | Description |
|---|---|
| Use binding attributes | Cleaner code with automatic deserialization |
| Configure connections | Use named connections for multiple instances |
| Handle failures | Return proper error codes or use retry policies |
| Scale appropriately | Consider trigger type for scaling needs |
| Monitor triggers | Track invocation metrics |
Trigger Selection Guide
Need HTTP endpoint? → HTTP Trigger
Run on schedule? → Timer Trigger
Process uploaded files? → Blob Trigger
Handle queue messages? → Queue/Service Bus Trigger
React to events? → Event Grid Trigger
Process streaming data? → Event Hubs Trigger
React to data changes? → Cosmos DB Trigger
Related Topics
- Input & Output Bindings — Connecting to data sources
- Error Handling — Handling failures
- Managed Identity — Secure authentication
Azure Integration Hub - Intermediate Level