azure-eventgrid-dotnet

Azure.Messaging.EventGrid (.NET)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "azure-eventgrid-dotnet" with this command: npx skills add claudedjale/skillset/claudedjale-skillset-azure-eventgrid-dotnet

Azure.Messaging.EventGrid (.NET)

Client library for publishing events to Azure Event Grid topics, domains, and namespaces.

Installation

For topics and domains (push delivery)

dotnet add package Azure.Messaging.EventGrid

For namespaces (pull delivery)

dotnet add package Azure.Messaging.EventGrid.Namespaces

For CloudNative CloudEvents interop

dotnet add package Microsoft.Azure.Messaging.EventGrid.CloudNativeCloudEvents

Current Version: 4.28.0 (stable)

Environment Variables

Topic/Domain endpoint

EVENT_GRID_TOPIC_ENDPOINT=https://<topic-name>.<region>.eventgrid.azure.net/api/events EVENT_GRID_TOPIC_KEY=<access-key>

Namespace endpoint (for pull delivery)

EVENT_GRID_NAMESPACE_ENDPOINT=https://<namespace>.<region>.eventgrid.azure.net EVENT_GRID_TOPIC_NAME=<topic-name> EVENT_GRID_SUBSCRIPTION_NAME=<subscription-name>

Client Hierarchy

Push Delivery (Topics/Domains) └── EventGridPublisherClient ├── SendEventAsync(EventGridEvent) ├── SendEventsAsync(IEnumerable<EventGridEvent>) ├── SendEventAsync(CloudEvent) └── SendEventsAsync(IEnumerable<CloudEvent>)

Pull Delivery (Namespaces) ├── EventGridSenderClient │ └── SendAsync(CloudEvent) └── EventGridReceiverClient ├── ReceiveAsync() ├── AcknowledgeAsync() ├── ReleaseAsync() └── RejectAsync()

Authentication

API Key Authentication

using Azure; using Azure.Messaging.EventGrid;

EventGridPublisherClient client = new( new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"), new AzureKeyCredential("<access-key>"));

Microsoft Entra ID (Recommended)

using Azure.Identity; using Azure.Messaging.EventGrid;

EventGridPublisherClient client = new( new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"), new DefaultAzureCredential());

SAS Token Authentication

string sasToken = EventGridPublisherClient.BuildSharedAccessSignature( new Uri(topicEndpoint), DateTimeOffset.UtcNow.AddHours(1), new AzureKeyCredential(topicKey));

var sasCredential = new AzureSasCredential(sasToken); EventGridPublisherClient client = new( new Uri(topicEndpoint), sasCredential);

Publishing Events

EventGridEvent Schema

EventGridPublisherClient client = new( new Uri(topicEndpoint), new AzureKeyCredential(topicKey));

// Single event EventGridEvent egEvent = new( subject: "orders/12345", eventType: "Order.Created", dataVersion: "1.0", data: new { OrderId = "12345", Amount = 99.99 });

await client.SendEventAsync(egEvent);

// Batch of events List<EventGridEvent> events = new() { new EventGridEvent( subject: "orders/12345", eventType: "Order.Created", dataVersion: "1.0", data: new OrderData { OrderId = "12345", Amount = 99.99 }), new EventGridEvent( subject: "orders/12346", eventType: "Order.Created", dataVersion: "1.0", data: new OrderData { OrderId = "12346", Amount = 149.99 }) };

await client.SendEventsAsync(events);

CloudEvent Schema

CloudEvent cloudEvent = new( source: "/orders/system", type: "Order.Created", data: new { OrderId = "12345", Amount = 99.99 });

cloudEvent.Subject = "orders/12345"; cloudEvent.Id = Guid.NewGuid().ToString(); cloudEvent.Time = DateTimeOffset.UtcNow;

await client.SendEventAsync(cloudEvent);

// Batch of CloudEvents List<CloudEvent> cloudEvents = new() { new CloudEvent("/orders", "Order.Created", new { OrderId = "1" }), new CloudEvent("/orders", "Order.Updated", new { OrderId = "2" }) };

await client.SendEventsAsync(cloudEvents);

Publishing to Event Grid Domain

// Events must specify the Topic property for domain routing List<EventGridEvent> events = new() { new EventGridEvent( subject: "orders/12345", eventType: "Order.Created", dataVersion: "1.0", data: new { OrderId = "12345" }) { Topic = "orders-topic" // Domain topic name }, new EventGridEvent( subject: "inventory/item-1", eventType: "Inventory.Updated", dataVersion: "1.0", data: new { ItemId = "item-1" }) { Topic = "inventory-topic" } };

await client.SendEventsAsync(events);

Custom Serialization

using System.Text.Json;

var serializerOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };

var customSerializer = new JsonObjectSerializer(serializerOptions);

EventGridEvent egEvent = new( subject: "orders/12345", eventType: "Order.Created", dataVersion: "1.0", data: customSerializer.Serialize(new OrderData { OrderId = "12345" }));

await client.SendEventAsync(egEvent);

Pull Delivery (Namespaces)

Send Events to Namespace Topic

using Azure; using Azure.Messaging; using Azure.Messaging.EventGrid.Namespaces;

var senderClient = new EventGridSenderClient( new Uri(namespaceEndpoint), topicName, new AzureKeyCredential(topicKey));

// Send single event CloudEvent cloudEvent = new("employee_source", "Employee.Created", new { Name = "John", Age = 30 }); await senderClient.SendAsync(cloudEvent);

// Send batch await senderClient.SendAsync(new[] { new CloudEvent("source", "type", new { Name = "Alice" }), new CloudEvent("source", "type", new { Name = "Bob" }) });

Receive and Process Events

var receiverClient = new EventGridReceiverClient( new Uri(namespaceEndpoint), topicName, subscriptionName, new AzureKeyCredential(topicKey));

// Receive events ReceiveResult result = await receiverClient.ReceiveAsync(maxEvents: 10);

List<string> lockTokensToAck = new(); List<string> lockTokensToRelease = new();

foreach (ReceiveDetails detail in result.Details) { CloudEvent cloudEvent = detail.Event; string lockToken = detail.BrokerProperties.LockToken;

try
{
    // Process the event
    Console.WriteLine($"Event: {cloudEvent.Type}, Data: {cloudEvent.Data}");
    lockTokensToAck.Add(lockToken);
}
catch (Exception)
{
    // Release for retry
    lockTokensToRelease.Add(lockToken);
}

}

// Acknowledge successfully processed events if (lockTokensToAck.Any()) { await receiverClient.AcknowledgeAsync(lockTokensToAck); }

// Release events for retry if (lockTokensToRelease.Any()) { await receiverClient.ReleaseAsync(lockTokensToRelease); }

Reject Events (Dead Letter)

// Reject events that cannot be processed await receiverClient.RejectAsync(new[] { lockToken });

Consuming Events (Azure Functions)

EventGridEvent Trigger

using Azure.Messaging.EventGrid; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.EventGrid;

public static class EventGridFunction { [FunctionName("ProcessEventGridEvent")] public static void Run( [EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { log.LogInformation($"Event Type: {eventGridEvent.EventType}"); log.LogInformation($"Subject: {eventGridEvent.Subject}"); log.LogInformation($"Data: {eventGridEvent.Data}"); } }

CloudEvent Trigger

using Azure.Messaging; using Microsoft.Azure.Functions.Worker;

public class CloudEventFunction { [Function("ProcessCloudEvent")] public void Run( [EventGridTrigger] CloudEvent cloudEvent, FunctionContext context) { var logger = context.GetLogger("ProcessCloudEvent"); logger.LogInformation($"Event Type: {cloudEvent.Type}"); logger.LogInformation($"Source: {cloudEvent.Source}"); logger.LogInformation($"Data: {cloudEvent.Data}"); } }

Parsing Events

Parse EventGridEvent

// From JSON string string json = "..."; // Event Grid webhook payload EventGridEvent[] events = EventGridEvent.ParseMany(BinaryData.FromString(json));

foreach (EventGridEvent egEvent in events) { if (egEvent.TryGetSystemEventData(out object systemEvent)) { // Handle system event switch (systemEvent) { case StorageBlobCreatedEventData blobCreated: Console.WriteLine($"Blob created: {blobCreated.Url}"); break; } } else { // Handle custom event var customData = egEvent.Data.ToObjectFromJson<MyCustomData>(); } }

Parse CloudEvent

CloudEvent[] cloudEvents = CloudEvent.ParseMany(BinaryData.FromString(json));

foreach (CloudEvent cloudEvent in cloudEvents) { var data = cloudEvent.Data.ToObjectFromJson<MyEventData>(); Console.WriteLine($"Type: {cloudEvent.Type}, Data: {data}"); }

System Events

// Common system event types using Azure.Messaging.EventGrid.SystemEvents;

// Storage events StorageBlobCreatedEventData blobCreated; StorageBlobDeletedEventData blobDeleted;

// Resource events ResourceWriteSuccessEventData resourceCreated; ResourceDeleteSuccessEventData resourceDeleted;

// App Service events WebAppUpdatedEventData webAppUpdated;

// Container Registry events ContainerRegistryImagePushedEventData imagePushed;

// IoT Hub events IotHubDeviceCreatedEventData deviceCreated;

Key Types Reference

Type Purpose

EventGridPublisherClient

Publish to topics/domains

EventGridSenderClient

Send to namespace topics

EventGridReceiverClient

Receive from namespace subscriptions

EventGridEvent

Event Grid native schema

CloudEvent

CloudEvents 1.0 schema

ReceiveResult

Pull delivery response

ReceiveDetails

Event with broker properties

BrokerProperties

Lock token, delivery count

Event Schemas Comparison

Feature EventGridEvent CloudEvent

Standard Azure-specific CNCF standard

Required fields subject, eventType, dataVersion, data source, type

Extensibility Limited Extension attributes

Interoperability Azure only Cross-platform

Best Practices

  • Use CloudEvents — Prefer CloudEvents for new implementations (industry standard)

  • Batch events — Send multiple events in one call for efficiency

  • Use Entra ID — Prefer managed identity over access keys

  • Idempotent handlers — Events may be delivered more than once

  • Set event TTL — Configure time-to-live for namespace events

  • Handle partial failures — Acknowledge/release events individually

  • Use dead-letter — Configure dead-letter for failed events

  • Validate schemas — Validate event data before processing

Error Handling

using Azure;

try { await client.SendEventAsync(cloudEvent); } catch (RequestFailedException ex) when (ex.Status == 401) { Console.WriteLine("Authentication failed - check credentials"); } catch (RequestFailedException ex) when (ex.Status == 403) { Console.WriteLine("Authorization failed - check RBAC permissions"); } catch (RequestFailedException ex) when (ex.Status == 413) { Console.WriteLine("Payload too large - max 1MB per event, 1MB total batch"); } catch (RequestFailedException ex) { Console.WriteLine($"Event Grid error: {ex.Status} - {ex.Message}"); }

Failover Pattern

try { var primaryClient = new EventGridPublisherClient(primaryUri, primaryKey); await primaryClient.SendEventsAsync(events); } catch (RequestFailedException) { // Failover to secondary region var secondaryClient = new EventGridPublisherClient(secondaryUri, secondaryKey); await secondaryClient.SendEventsAsync(events); }

Related SDKs

SDK Purpose Install

Azure.Messaging.EventGrid

Topics/Domains (this SDK) dotnet add package Azure.Messaging.EventGrid

Azure.Messaging.EventGrid.Namespaces

Pull delivery dotnet add package Azure.Messaging.EventGrid.Namespaces

Azure.Identity

Authentication dotnet add package Azure.Identity

Microsoft.Azure.WebJobs.Extensions.EventGrid

Azure Functions trigger dotnet add package Microsoft.Azure.WebJobs.Extensions.EventGrid

Reference Links

Resource URL

NuGet Package https://www.nuget.org/packages/Azure.Messaging.EventGrid

API Reference https://learn.microsoft.com/dotnet/api/azure.messaging.eventgrid

Quickstart https://learn.microsoft.com/azure/event-grid/custom-event-quickstart

Pull Delivery https://learn.microsoft.com/azure/event-grid/pull-delivery-overview

GitHub Source https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventgrid/Azure.Messaging.EventGrid

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

azure-observability

No summary provided by upstream source.

Repository SourceNeeds Review
General

azure-appconfiguration-java

No summary provided by upstream source.

Repository SourceNeeds Review
General

copilot-sdk

No summary provided by upstream source.

Repository SourceNeeds Review
General

azure-compliance

No summary provided by upstream source.

Repository SourceNeeds Review