|
Add this skill
npx mdskills install sickn33/azure-eventgrid-dotnetComprehensive Azure Event Grid SDK reference with clear code examples and authentication patterns
1---2name: azure-eventgrid-dotnet3description: |4 Azure Event Grid SDK for .NET. Client library for publishing and consuming events with Azure Event Grid. Use for event-driven architectures, pub/sub messaging, CloudEvents, and EventGridEvents. Triggers: "Event Grid", "EventGridPublisherClient", "CloudEvent", "EventGridEvent", "publish events .NET", "event-driven", "pub/sub".5package: Azure.Messaging.EventGrid6---78# Azure.Messaging.EventGrid (.NET)910Client library for publishing events to Azure Event Grid topics, domains, and namespaces.1112## Installation1314```bash15# For topics and domains (push delivery)16dotnet add package Azure.Messaging.EventGrid1718# For namespaces (pull delivery)19dotnet add package Azure.Messaging.EventGrid.Namespaces2021# For CloudNative CloudEvents interop22dotnet add package Microsoft.Azure.Messaging.EventGrid.CloudNativeCloudEvents23```2425**Current Version**: 4.28.0 (stable)2627## Environment Variables2829```bash30# Topic/Domain endpoint31EVENT_GRID_TOPIC_ENDPOINT=https://<topic-name>.<region>.eventgrid.azure.net/api/events32EVENT_GRID_TOPIC_KEY=<access-key>3334# Namespace endpoint (for pull delivery)35EVENT_GRID_NAMESPACE_ENDPOINT=https://<namespace>.<region>.eventgrid.azure.net36EVENT_GRID_TOPIC_NAME=<topic-name>37EVENT_GRID_SUBSCRIPTION_NAME=<subscription-name>38```3940## Client Hierarchy4142```43Push Delivery (Topics/Domains)44└── EventGridPublisherClient45 ├── SendEventAsync(EventGridEvent)46 ├── SendEventsAsync(IEnumerable<EventGridEvent>)47 ├── SendEventAsync(CloudEvent)48 └── SendEventsAsync(IEnumerable<CloudEvent>)4950Pull Delivery (Namespaces)51├── EventGridSenderClient52│ └── SendAsync(CloudEvent)53└── EventGridReceiverClient54 ├── ReceiveAsync()55 ├── AcknowledgeAsync()56 ├── ReleaseAsync()57 └── RejectAsync()58```5960## Authentication6162### API Key Authentication6364```csharp65using Azure;66using Azure.Messaging.EventGrid;6768EventGridPublisherClient client = new(69 new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"),70 new AzureKeyCredential("<access-key>"));71```7273### Microsoft Entra ID (Recommended)7475```csharp76using Azure.Identity;77using Azure.Messaging.EventGrid;7879EventGridPublisherClient client = new(80 new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"),81 new DefaultAzureCredential());82```8384### SAS Token Authentication8586```csharp87string sasToken = EventGridPublisherClient.BuildSharedAccessSignature(88 new Uri(topicEndpoint),89 DateTimeOffset.UtcNow.AddHours(1),90 new AzureKeyCredential(topicKey));9192var sasCredential = new AzureSasCredential(sasToken);93EventGridPublisherClient client = new(94 new Uri(topicEndpoint),95 sasCredential);96```9798## Publishing Events99100### EventGridEvent Schema101102```csharp103EventGridPublisherClient client = new(104 new Uri(topicEndpoint),105 new AzureKeyCredential(topicKey));106107// Single event108EventGridEvent egEvent = new(109 subject: "orders/12345",110 eventType: "Order.Created",111 dataVersion: "1.0",112 data: new { OrderId = "12345", Amount = 99.99 });113114await client.SendEventAsync(egEvent);115116// Batch of events117List<EventGridEvent> events = new()118{119 new EventGridEvent(120 subject: "orders/12345",121 eventType: "Order.Created",122 dataVersion: "1.0",123 data: new OrderData { OrderId = "12345", Amount = 99.99 }),124 new EventGridEvent(125 subject: "orders/12346",126 eventType: "Order.Created",127 dataVersion: "1.0",128 data: new OrderData { OrderId = "12346", Amount = 149.99 })129};130131await client.SendEventsAsync(events);132```133134### CloudEvent Schema135136```csharp137CloudEvent cloudEvent = new(138 source: "/orders/system",139 type: "Order.Created",140 data: new { OrderId = "12345", Amount = 99.99 });141142cloudEvent.Subject = "orders/12345";143cloudEvent.Id = Guid.NewGuid().ToString();144cloudEvent.Time = DateTimeOffset.UtcNow;145146await client.SendEventAsync(cloudEvent);147148// Batch of CloudEvents149List<CloudEvent> cloudEvents = new()150{151 new CloudEvent("/orders", "Order.Created", new { OrderId = "1" }),152 new CloudEvent("/orders", "Order.Updated", new { OrderId = "2" })153};154155await client.SendEventsAsync(cloudEvents);156```157158### Publishing to Event Grid Domain159160```csharp161// Events must specify the Topic property for domain routing162List<EventGridEvent> events = new()163{164 new EventGridEvent(165 subject: "orders/12345",166 eventType: "Order.Created",167 dataVersion: "1.0",168 data: new { OrderId = "12345" })169 {170 Topic = "orders-topic" // Domain topic name171 },172 new EventGridEvent(173 subject: "inventory/item-1",174 eventType: "Inventory.Updated",175 dataVersion: "1.0",176 data: new { ItemId = "item-1" })177 {178 Topic = "inventory-topic"179 }180};181182await client.SendEventsAsync(events);183```184185### Custom Serialization186187```csharp188using System.Text.Json;189190var serializerOptions = new JsonSerializerOptions191{192 PropertyNamingPolicy = JsonNamingPolicy.CamelCase193};194195var customSerializer = new JsonObjectSerializer(serializerOptions);196197EventGridEvent egEvent = new(198 subject: "orders/12345",199 eventType: "Order.Created",200 dataVersion: "1.0",201 data: customSerializer.Serialize(new OrderData { OrderId = "12345" }));202203await client.SendEventAsync(egEvent);204```205206## Pull Delivery (Namespaces)207208### Send Events to Namespace Topic209210```csharp211using Azure;212using Azure.Messaging;213using Azure.Messaging.EventGrid.Namespaces;214215var senderClient = new EventGridSenderClient(216 new Uri(namespaceEndpoint),217 topicName,218 new AzureKeyCredential(topicKey));219220// Send single event221CloudEvent cloudEvent = new("employee_source", "Employee.Created",222 new { Name = "John", Age = 30 });223await senderClient.SendAsync(cloudEvent);224225// Send batch226await senderClient.SendAsync(new[]227{228 new CloudEvent("source", "type", new { Name = "Alice" }),229 new CloudEvent("source", "type", new { Name = "Bob" })230});231```232233### Receive and Process Events234235```csharp236var receiverClient = new EventGridReceiverClient(237 new Uri(namespaceEndpoint),238 topicName,239 subscriptionName,240 new AzureKeyCredential(topicKey));241242// Receive events243ReceiveResult result = await receiverClient.ReceiveAsync(maxEvents: 10);244245List<string> lockTokensToAck = new();246List<string> lockTokensToRelease = new();247248foreach (ReceiveDetails detail in result.Details)249{250 CloudEvent cloudEvent = detail.Event;251 string lockToken = detail.BrokerProperties.LockToken;252253 try254 {255 // Process the event256 Console.WriteLine($"Event: {cloudEvent.Type}, Data: {cloudEvent.Data}");257 lockTokensToAck.Add(lockToken);258 }259 catch (Exception)260 {261 // Release for retry262 lockTokensToRelease.Add(lockToken);263 }264}265266// Acknowledge successfully processed events267if (lockTokensToAck.Any())268{269 await receiverClient.AcknowledgeAsync(lockTokensToAck);270}271272// Release events for retry273if (lockTokensToRelease.Any())274{275 await receiverClient.ReleaseAsync(lockTokensToRelease);276}277```278279### Reject Events (Dead Letter)280281```csharp282// Reject events that cannot be processed283await receiverClient.RejectAsync(new[] { lockToken });284```285286## Consuming Events (Azure Functions)287288### EventGridEvent Trigger289290```csharp291using Azure.Messaging.EventGrid;292using Microsoft.Azure.WebJobs;293using Microsoft.Azure.WebJobs.Extensions.EventGrid;294295public static class EventGridFunction296{297 [FunctionName("ProcessEventGridEvent")]298 public static void Run(299 [EventGridTrigger] EventGridEvent eventGridEvent,300 ILogger log)301 {302 log.LogInformation($"Event Type: {eventGridEvent.EventType}");303 log.LogInformation($"Subject: {eventGridEvent.Subject}");304 log.LogInformation($"Data: {eventGridEvent.Data}");305 }306}307```308309### CloudEvent Trigger310311```csharp312using Azure.Messaging;313using Microsoft.Azure.Functions.Worker;314315public class CloudEventFunction316{317 [Function("ProcessCloudEvent")]318 public void Run(319 [EventGridTrigger] CloudEvent cloudEvent,320 FunctionContext context)321 {322 var logger = context.GetLogger("ProcessCloudEvent");323 logger.LogInformation($"Event Type: {cloudEvent.Type}");324 logger.LogInformation($"Source: {cloudEvent.Source}");325 logger.LogInformation($"Data: {cloudEvent.Data}");326 }327}328```329330## Parsing Events331332### Parse EventGridEvent333334```csharp335// From JSON string336string json = "..."; // Event Grid webhook payload337EventGridEvent[] events = EventGridEvent.ParseMany(BinaryData.FromString(json));338339foreach (EventGridEvent egEvent in events)340{341 if (egEvent.TryGetSystemEventData(out object systemEvent))342 {343 // Handle system event344 switch (systemEvent)345 {346 case StorageBlobCreatedEventData blobCreated:347 Console.WriteLine($"Blob created: {blobCreated.Url}");348 break;349 }350 }351 else352 {353 // Handle custom event354 var customData = egEvent.Data.ToObjectFromJson<MyCustomData>();355 }356}357```358359### Parse CloudEvent360361```csharp362CloudEvent[] cloudEvents = CloudEvent.ParseMany(BinaryData.FromString(json));363364foreach (CloudEvent cloudEvent in cloudEvents)365{366 var data = cloudEvent.Data.ToObjectFromJson<MyEventData>();367 Console.WriteLine($"Type: {cloudEvent.Type}, Data: {data}");368}369```370371## System Events372373```csharp374// Common system event types375using Azure.Messaging.EventGrid.SystemEvents;376377// Storage events378StorageBlobCreatedEventData blobCreated;379StorageBlobDeletedEventData blobDeleted;380381// Resource events382ResourceWriteSuccessEventData resourceCreated;383ResourceDeleteSuccessEventData resourceDeleted;384385// App Service events386WebAppUpdatedEventData webAppUpdated;387388// Container Registry events389ContainerRegistryImagePushedEventData imagePushed;390391// IoT Hub events392IotHubDeviceCreatedEventData deviceCreated;393```394395## Key Types Reference396397| Type | Purpose |398|------|---------|399| `EventGridPublisherClient` | Publish to topics/domains |400| `EventGridSenderClient` | Send to namespace topics |401| `EventGridReceiverClient` | Receive from namespace subscriptions |402| `EventGridEvent` | Event Grid native schema |403| `CloudEvent` | CloudEvents 1.0 schema |404| `ReceiveResult` | Pull delivery response |405| `ReceiveDetails` | Event with broker properties |406| `BrokerProperties` | Lock token, delivery count |407408## Event Schemas Comparison409410| Feature | EventGridEvent | CloudEvent |411|---------|----------------|------------|412| Standard | Azure-specific | CNCF standard |413| Required fields | subject, eventType, dataVersion, data | source, type |414| Extensibility | Limited | Extension attributes |415| Interoperability | Azure only | Cross-platform |416417## Best Practices4184191. **Use CloudEvents** — Prefer CloudEvents for new implementations (industry standard)4202. **Batch events** — Send multiple events in one call for efficiency4213. **Use Entra ID** — Prefer managed identity over access keys4224. **Idempotent handlers** — Events may be delivered more than once4235. **Set event TTL** — Configure time-to-live for namespace events4246. **Handle partial failures** — Acknowledge/release events individually4257. **Use dead-letter** — Configure dead-letter for failed events4268. **Validate schemas** — Validate event data before processing427428## Error Handling429430```csharp431using Azure;432433try434{435 await client.SendEventAsync(cloudEvent);436}437catch (RequestFailedException ex) when (ex.Status == 401)438{439 Console.WriteLine("Authentication failed - check credentials");440}441catch (RequestFailedException ex) when (ex.Status == 403)442{443 Console.WriteLine("Authorization failed - check RBAC permissions");444}445catch (RequestFailedException ex) when (ex.Status == 413)446{447 Console.WriteLine("Payload too large - max 1MB per event, 1MB total batch");448}449catch (RequestFailedException ex)450{451 Console.WriteLine($"Event Grid error: {ex.Status} - {ex.Message}");452}453```454455## Failover Pattern456457```csharp458try459{460 var primaryClient = new EventGridPublisherClient(primaryUri, primaryKey);461 await primaryClient.SendEventsAsync(events);462}463catch (RequestFailedException)464{465 // Failover to secondary region466 var secondaryClient = new EventGridPublisherClient(secondaryUri, secondaryKey);467 await secondaryClient.SendEventsAsync(events);468}469```470471## Related SDKs472473| SDK | Purpose | Install |474|-----|---------|---------|475| `Azure.Messaging.EventGrid` | Topics/Domains (this SDK) | `dotnet add package Azure.Messaging.EventGrid` |476| `Azure.Messaging.EventGrid.Namespaces` | Pull delivery | `dotnet add package Azure.Messaging.EventGrid.Namespaces` |477| `Azure.Identity` | Authentication | `dotnet add package Azure.Identity` |478| `Microsoft.Azure.WebJobs.Extensions.EventGrid` | Azure Functions trigger | `dotnet add package Microsoft.Azure.WebJobs.Extensions.EventGrid` |479480## Reference Links481482| Resource | URL |483|----------|-----|484| NuGet Package | https://www.nuget.org/packages/Azure.Messaging.EventGrid |485| API Reference | https://learn.microsoft.com/dotnet/api/azure.messaging.eventgrid |486| Quickstart | https://learn.microsoft.com/azure/event-grid/custom-event-quickstart |487| Pull Delivery | https://learn.microsoft.com/azure/event-grid/pull-delivery-overview |488| GitHub Source | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventgrid/Azure.Messaging.EventGrid |489
Full transparency — inspect the skill content before installing.