Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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.
.claude/skills/azure-eventgrid-dotnet/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | — | — |
| case-15 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-05 | ✗→✓ | ▲ Improved | — | — |
| case-06 | ✓→✓ | = Same ✓ | — | — |
Client library for publishing events to Azure Event Grid topics, domains, and namespaces.
bash# 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)
bash# 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>
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()csharpusing Azure; using Azure.Messaging.EventGrid; EventGridPublisherClient client = new( new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"), new AzureKeyCredential("<access-key>"));
csharpusing Azure.Identity; using Azure.Messaging.EventGrid; EventGridPublisherClient client = new( new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"), new DefaultAzureCredential());
csharpstring 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);
csharpEventGridPublisherClient 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);
csharpCloudEvent 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);
csharp// 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);
csharpusing 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);
csharpusing 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" }) });
csharpvar 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); }
csharp// Reject events that cannot be processed await receiverClient.RejectAsync(new[] { lockToken });
csharpusing 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}"); } }
csharpusing 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}"); } }
csharp// 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>(); } }
csharpCloudEvent[] cloudEvents = CloudEvent.ParseMany(BinaryData.FromString(json)); foreach (CloudEvent cloudEvent in cloudEvents) { var data = cloudEvent.Data.ToObjectFromJson<MyEventData>(); Console.WriteLine($"Type: {cloudEvent.Type}, Data: {data}"); }
csharp// 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;
| 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 |
| 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 |
csharpusing 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}"); }
csharptry { 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); }
| 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 |
| 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 |
This skill is applicable to execute the workflow or actions described in the overview.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.