Building Event-Driven Serverless Apps with .NET 8, Azure Container Apps, and Dapr

Mahmut Sarıkaya 4 dk okuma 4 Görüntülenme 0
Building Event-Driven Serverless Apps with .NET 8, Azure Container Apps, and Dapr

Why event-driven serverless matters for modern .NET workloads

More than 70% of new cloud-native projects adopt an event-driven architecture to achieve scalability and loose coupling. For .NET developers, the challenge is to combine the familiarity of C# with a truly serverless execution model that reacts to messages, timers, or HTTP calls without managing servers.

Core components: .NET 8, Azure Container Apps, and Dapr

.NET 8 introduces native support for minimal APIs, async streams, and improved AOT compilation, which reduces cold‑start latency. Azure Container Apps offers a fully managed, Kubernetes‑based platform that scales to zero, making it ideal for serverless workloads. Dapr (Distributed Application Runtime) adds building blocks—pub/sub, state stores, bindings—through sidecars, allowing .NET code to stay clean while handling events.

System requirements and quick start checklist

Before you begin, ensure you have:

  • Azure CLI 2.55+ installed.
  • Docker Desktop (or a compatible container runtime).
  • .NET SDK 8.0.x.
  • An Azure subscription with Contributor rights.

Follow these steps to spin up a sample order‑processing service.

Step‑by‑step: Create a minimal API that publishes events via Dapr

First, scaffold a new .NET 8 web project.

dotnet new web -n OrderService

Navigate into the folder and add the Dapr client package.

cd OrderService
dotnet add package Dapr.Client

Replace Program.cs with the following code. It defines a POST endpoint /orders that publishes an order-created event to the Dapr pub/sub component named pubsub.

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using Dapr.Client;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDaprClient();

var app = builder.Build();

app.MapPost("/orders", async (Order order, DaprClient dapr) =>
{
await dapr.PublishEventAsync("pubsub", "order-created", order);
return Results.Accepted();
});

app.Run();

public record Order(string Id, string Product, int Quantity);

Build the container image.

dotnet publish -c Release -o out
docker build -t sarikayadev/order-service:latest .

Deploy to Azure Container Apps with Dapr enabled

Create a resource group and an Azure Container Apps environment.

az group create -n dapr-demo-rg -l eastus
az containerapp env create -n dapr-env -g dapr-demo-rg --location eastus

Deploy the container and turn on Dapr sidecar (version 1.12 is stable as of 2024).

az containerapp create \
  --name order-service \
  --resource-group dapr-demo-rg \
  --environment dapr-env \
  --image sarikayadev/order-service:latest \
  --ingress external \
  --target-port 80 \
  --dapr-enabled true \
  --dapr-app-id order-service \
  --dapr-app-port 80 \
  --dapr-config "dapr-config"

The --dapr-enabled true flag injects the Dapr sidecar, which automatically reads the components folder you will upload next.

Configure a pub/sub component (Azure Service Bus) for Dapr

Create a Service Bus namespace (standard tier) and a topic called orders. Grab the connection string from the Azure portal.

az servicebus namespace create -g dapr-demo-rg -n orderbus --sku Standard
az servicebus topic create -g dapr-demo-rg --namespace-name orderbus -n orders

Save the following YAML as pubsub.yaml and upload it to the Dapr components folder of the Container App.

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
namespace: default
spec:
type: pubsub.azure.servicebus
version: v1
metadata:
- name: connectionString
value: "Endpoint=sb://orderbus.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_KEY"
- name: consumerID
value: "order-service"

Upload with:

az containerapp env dapr component set \
  --name dapr-env \
  --resource-group dapr-demo-rg \
  --component-file pubsub.yaml

Consume the event with a second microservice

Build a simple subscriber that logs every order. The Dapr sidecar will invoke the endpoint automatically.

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using Dapr;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapSubscribeHandler();

app.MapPost("/order-created", (Order order) =>
{
Console.WriteLine($"Received order {order.Id} for {order.Product}");
return Results.Ok();
});

app.Run();

public record Order(string Id, string Product, int Quantity);

Deploy this service the same way, giving it a distinct --dapr-app-id subscriber. Dapr will route order-created events to /order-created of the subscriber automatically.

Practical tips for production readiness

  • Cold‑start mitigation: Enable .NET 8 native AOT for the container image; it can shave 30‑40% off first‑request latency.
  • Observability: Turn on Dapr metrics and send them to Azure Monitor. Add --enable-dapr-metrics true in the Container App definition.
  • Retry policies: Configure Dapr pub/sub with deadLetterTopic and maxDeliveryCount to avoid message loss.
  • Security: Store Service Bus connection strings in Azure Key Vault and reference them via secretRef in the component YAML.

Conclusion

By pairing .NET 8’s lightweight APIs with Azure Container Apps’ serverless scaling and Dapr’s event‑driven building blocks, you can construct microservices that start at zero, react instantly to events, and stay maintainable. The approach eliminates the need for custom orchestration code, lets you focus on business logic, and leverages Azure’s managed infrastructure for reliability.

Sources

  • Microsoft Docs – Azure Container Apps
  • Dapr.io – Pub/Sub building block
  • .NET Blog – .NET 8 release notes

Author: Mahmut Sarıkaya — sarikayadev.com

Etiketler: #.NET 8 #Azure Container Apps #Dapr #event-driven #serverless
Paylaş:
M

Yazar

Mahmut Sarıkaya

yazılım Geliştirici

Yorumlar

Henüz yorum yok. İlk yorumu siz yapın!

Yorum Bırakın

2 + 3 =