[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-81e7e0f7-3dd4-47ed-8b7d-7c72a8ac6176":3,"$f0KKOGwtpseVBlXLLNKYc1bMA3_Mcr5AqdEcy4KGLowY":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"81e7e0f7-3dd4-47ed-8b7d-7c72a8ac6176","azure-eventgrid-dotnet","Azure Event Grid SDK for .NET。用于发布和消费 Azure Event Grid 事件的客户端库。适用于事件驱动架构、发布\u002F订阅消息、CloudEvents 和 EventGridEvents。","cat_coding_devops","mod_coding","sickn33,coding","---\nname: azure-eventgrid-dotnet\ndescription: Azure Event Grid SDK for .NET. Client library for publishing and consuming events with Azure Event Grid. Use for event-driven architectures, pub\u002Fsub messaging, CloudEvents, and EventGridEvents.\nrisk: unknown\nsource: community\ndate_added: '2026-02-27'\n---\n\n# Azure.Messaging.EventGrid (.NET)\n\nClient library for publishing events to Azure Event Grid topics, domains, and namespaces.\n\n## Installation\n\n```bash\n# For topics and domains (push delivery)\ndotnet add package Azure.Messaging.EventGrid\n\n# For namespaces (pull delivery)\ndotnet add package Azure.Messaging.EventGrid.Namespaces\n\n# For CloudNative CloudEvents interop\ndotnet add package Microsoft.Azure.Messaging.EventGrid.CloudNativeCloudEvents\n```\n\n**Current Version**: 4.28.0 (stable)\n\n## Environment Variables\n\n```bash\n# Topic\u002FDomain endpoint\nEVENT_GRID_TOPIC_ENDPOINT=https:\u002F\u002F\u003Ctopic-name>.\u003Cregion>.eventgrid.azure.net\u002Fapi\u002Fevents\nEVENT_GRID_TOPIC_KEY=\u003Caccess-key>\n\n# Namespace endpoint (for pull delivery)\nEVENT_GRID_NAMESPACE_ENDPOINT=https:\u002F\u002F\u003Cnamespace>.\u003Cregion>.eventgrid.azure.net\nEVENT_GRID_TOPIC_NAME=\u003Ctopic-name>\nEVENT_GRID_SUBSCRIPTION_NAME=\u003Csubscription-name>\n```\n\n## Client Hierarchy\n\n```\nPush Delivery (Topics\u002FDomains)\n└── EventGridPublisherClient\n    ├── SendEventAsync(EventGridEvent)\n    ├── SendEventsAsync(IEnumerable\u003CEventGridEvent>)\n    ├── SendEventAsync(CloudEvent)\n    └── SendEventsAsync(IEnumerable\u003CCloudEvent>)\n\nPull Delivery (Namespaces)\n├── EventGridSenderClient\n│   └── SendAsync(CloudEvent)\n└── EventGridReceiverClient\n    ├── ReceiveAsync()\n    ├── AcknowledgeAsync()\n    ├── ReleaseAsync()\n    └── RejectAsync()\n```\n\n## Authentication\n\n### API Key Authentication\n\n```csharp\nusing Azure;\nusing Azure.Messaging.EventGrid;\n\nEventGridPublisherClient client = new(\n    new Uri(\"https:\u002F\u002Fmytopic.eastus-1.eventgrid.azure.net\u002Fapi\u002Fevents\"),\n    new AzureKeyCredential(\"\u003Caccess-key>\"));\n```\n\n### Microsoft Entra ID (Recommended)\n\n```csharp\nusing Azure.Identity;\nusing Azure.Messaging.EventGrid;\n\nEventGridPublisherClient client = new(\n    new Uri(\"https:\u002F\u002Fmytopic.eastus-1.eventgrid.azure.net\u002Fapi\u002Fevents\"),\n    new DefaultAzureCredential());\n```\n\n### SAS Token Authentication\n\n```csharp\nstring sasToken = EventGridPublisherClient.BuildSharedAccessSignature(\n    new Uri(topicEndpoint),\n    DateTimeOffset.UtcNow.AddHours(1),\n    new AzureKeyCredential(topicKey));\n\nvar sasCredential = new AzureSasCredential(sasToken);\nEventGridPublisherClient client = new(\n    new Uri(topicEndpoint),\n    sasCredential);\n```\n\n## Publishing Events\n\n### EventGridEvent Schema\n\n```csharp\nEventGridPublisherClient client = new(\n    new Uri(topicEndpoint),\n    new AzureKeyCredential(topicKey));\n\n\u002F\u002F Single event\nEventGridEvent egEvent = new(\n    subject: \"orders\u002F12345\",\n    eventType: \"Order.Created\",\n    dataVersion: \"1.0\",\n    data: new { OrderId = \"12345\", Amount = 99.99 });\n\nawait client.SendEventAsync(egEvent);\n\n\u002F\u002F Batch of events\nList\u003CEventGridEvent> events = new()\n{\n    new EventGridEvent(\n        subject: \"orders\u002F12345\",\n        eventType: \"Order.Created\",\n        dataVersion: \"1.0\",\n        data: new OrderData { OrderId = \"12345\", Amount = 99.99 }),\n    new EventGridEvent(\n        subject: \"orders\u002F12346\",\n        eventType: \"Order.Created\",\n        dataVersion: \"1.0\",\n        data: new OrderData { OrderId = \"12346\", Amount = 149.99 })\n};\n\nawait client.SendEventsAsync(events);\n```\n\n### CloudEvent Schema\n\n```csharp\nCloudEvent cloudEvent = new(\n    source: \"\u002Forders\u002Fsystem\",\n    type: \"Order.Created\",\n    data: new { OrderId = \"12345\", Amount = 99.99 });\n\ncloudEvent.Subject = \"orders\u002F12345\";\ncloudEvent.Id = Guid.NewGuid().ToString();\ncloudEvent.Time = DateTimeOffset.UtcNow;\n\nawait client.SendEventAsync(cloudEvent);\n\n\u002F\u002F Batch of CloudEvents\nList\u003CCloudEvent> cloudEvents = new()\n{\n    new CloudEvent(\"\u002Forders\", \"Order.Created\", new { OrderId = \"1\" }),\n    new CloudEvent(\"\u002Forders\", \"Order.Updated\", new { OrderId = \"2\" })\n};\n\nawait client.SendEventsAsync(cloudEvents);\n```\n\n### Publishing to Event Grid Domain\n\n```csharp\n\u002F\u002F Events must specify the Topic property for domain routing\nList\u003CEventGridEvent> events = new()\n{\n    new EventGridEvent(\n        subject: \"orders\u002F12345\",\n        eventType: \"Order.Created\",\n        dataVersion: \"1.0\",\n        data: new { OrderId = \"12345\" })\n    {\n        Topic = \"orders-topic\"  \u002F\u002F Domain topic name\n    },\n    new EventGridEvent(\n        subject: \"inventory\u002Fitem-1\",\n        eventType: \"Inventory.Updated\",\n        dataVersion: \"1.0\",\n        data: new { ItemId = \"item-1\" })\n    {\n        Topic = \"inventory-topic\"\n    }\n};\n\nawait client.SendEventsAsync(events);\n```\n\n### Custom Serialization\n\n```csharp\nusing System.Text.Json;\n\nvar serializerOptions = new JsonSerializerOptions\n{\n    PropertyNamingPolicy = JsonNamingPolicy.CamelCase\n};\n\nvar customSerializer = new JsonObjectSerializer(serializerOptions);\n\nEventGridEvent egEvent = new(\n    subject: \"orders\u002F12345\",\n    eventType: \"Order.Created\",\n    dataVersion: \"1.0\",\n    data: customSerializer.Serialize(new OrderData { OrderId = \"12345\" }));\n\nawait client.SendEventAsync(egEvent);\n```\n\n## Pull Delivery (Namespaces)\n\n### Send Events to Namespace Topic\n\n```csharp\nusing Azure;\nusing Azure.Messaging;\nusing Azure.Messaging.EventGrid.Namespaces;\n\nvar senderClient = new EventGridSenderClient(\n    new Uri(namespaceEndpoint),\n    topicName,\n    new AzureKeyCredential(topicKey));\n\n\u002F\u002F Send single event\nCloudEvent cloudEvent = new(\"employee_source\", \"Employee.Created\", \n    new { Name = \"John\", Age = 30 });\nawait senderClient.SendAsync(cloudEvent);\n\n\u002F\u002F Send batch\nawait senderClient.SendAsync(new[]\n{\n    new CloudEvent(\"source\", \"type\", new { Name = \"Alice\" }),\n    new CloudEvent(\"source\", \"type\", new { Name = \"Bob\" })\n});\n```\n\n### Receive and Process Events\n\n```csharp\nvar receiverClient = new EventGridReceiverClient(\n    new Uri(namespaceEndpoint),\n    topicName,\n    subscriptionName,\n    new AzureKeyCredential(topicKey));\n\n\u002F\u002F Receive events\nReceiveResult result = await receiverClient.ReceiveAsync(maxEvents: 10);\n\nList\u003Cstring> lockTokensToAck = new();\nList\u003Cstring> lockTokensToRelease = new();\n\nforeach (ReceiveDetails detail in result.Details)\n{\n    CloudEvent cloudEvent = detail.Event;\n    string lockToken = detail.BrokerProperties.LockToken;\n    \n    try\n    {\n        \u002F\u002F Process the event\n        Console.WriteLine($\"Event: {cloudEvent.Type}, Data: {cloudEvent.Data}\");\n        lockTokensToAck.Add(lockToken);\n    }\n    catch (Exception)\n    {\n        \u002F\u002F Release for retry\n        lockTokensToRelease.Add(lockToken);\n    }\n}\n\n\u002F\u002F Acknowledge successfully processed events\nif (lockTokensToAck.Any())\n{\n    await receiverClient.AcknowledgeAsync(lockTokensToAck);\n}\n\n\u002F\u002F Release events for retry\nif (lockTokensToRelease.Any())\n{\n    await receiverClient.ReleaseAsync(lockTokensToRelease);\n}\n```\n\n### Reject Events (Dead Letter)\n\n```csharp\n\u002F\u002F Reject events that cannot be processed\nawait receiverClient.RejectAsync(new[] { lockToken });\n```\n\n## Consuming Events (Azure Functions)\n\n### EventGridEvent Trigger\n\n```csharp\nusing Azure.Messaging.EventGrid;\nusing Microsoft.Azure.WebJobs;\nusing Microsoft.Azure.WebJobs.Extensions.EventGrid;\n\npublic static class EventGridFunction\n{\n    [FunctionName(\"ProcessEventGridEvent\")]\n    public static void Run(\n        [EventGridTrigger] EventGridEvent eventGridEvent,\n        ILogger log)\n    {\n        log.LogInformation($\"Event Type: {eventGridEvent.EventType}\");\n        log.LogInformation($\"Subject: {eventGridEvent.Subject}\");\n        log.LogInformation($\"Data: {eventGridEvent.Data}\");\n    }\n}\n```\n\n### CloudEvent Trigger\n\n```csharp\nusing Azure.Messaging;\nusing Microsoft.Azure.Functions.Worker;\n\npublic class CloudEventFunction\n{\n    [Function(\"ProcessCloudEvent\")]\n    public void Run(\n        [EventGridTrigger] CloudEvent cloudEvent,\n        FunctionContext context)\n    {\n        var logger = context.GetLogger(\"ProcessCloudEvent\");\n        logger.LogInformation($\"Event Type: {cloudEvent.Type}\");\n        logger.LogInformation($\"Source: {cloudEvent.Source}\");\n        logger.LogInformation($\"Data: {cloudEvent.Data}\");\n    }\n}\n```\n\n## Parsing Events\n\n### Parse EventGridEvent\n\n```csharp\n\u002F\u002F From JSON string\nstring json = \"...\"; \u002F\u002F Event Grid webhook payload\nEventGridEvent[] events = EventGridEvent.ParseMany(BinaryData.FromString(json));\n\nforeach (EventGridEvent egEvent in events)\n{\n    if (egEvent.TryGetSystemEventData(out object systemEvent))\n    {\n        \u002F\u002F Handle system event\n        switch (systemEvent)\n        {\n            case StorageBlobCreatedEventData blobCreated:\n                Console.WriteLine($\"Blob created: {blobCreated.Url}\");\n                break;\n        }\n    }\n    else\n    {\n        \u002F\u002F Handle custom event\n        var customData = egEvent.Data.ToObjectFromJson\u003CMyCustomData>();\n    }\n}\n```\n\n### Parse CloudEvent\n\n```csharp\nCloudEvent[] cloudEvents = CloudEvent.ParseMany(BinaryData.FromString(json));\n\nforeach (CloudEvent cloudEvent in cloudEvents)\n{\n    var data = cloudEvent.Data.ToObjectFromJson\u003CMyEventData>();\n    Console.WriteLine($\"Type: {cloudEvent.Type}, Data: {data}\");\n}\n```\n\n## System Events\n\n```csharp\n\u002F\u002F Common system event types\nusing Azure.Messaging.EventGrid.SystemEvents;\n\n\u002F\u002F Storage events\nStorageBlobCreatedEventData blobCreated;\nStorageBlobDeletedEventData blobDeleted;\n\n\u002F\u002F Resource events\nResourceWriteSuccessEventData resourceCreated;\nResourceDeleteSuccessEventData resourceDeleted;\n\n\u002F\u002F App Service events\nWebAppUpdatedEventData webAppUpdated;\n\n\u002F\u002F Container Registry events\nContainerRegistryImagePushedEventData imagePushed;\n\n\u002F\u002F IoT Hub events\nIotHubDeviceCreatedEventData deviceCreated;\n```\n\n## Key Types Reference\n\n| Type | Purpose |\n|------|---------|\n| `EventGridPublisherClient` | Publish to topics\u002Fdomains |\n| `EventGridSenderClient` | Send to namespace topics |\n| `EventGridReceiverClient` | Receive from namespace subscriptions |\n| `EventGridEvent` | Event Grid native schema |\n| `CloudEvent` | CloudEvents 1.0 schema |\n| `ReceiveResult` | Pull delivery response |\n| `ReceiveDetails` | Event with broker properties |\n| `BrokerProperties` | Lock token, delivery count |\n\n## Event Schemas Comparison\n\n| Feature | EventGridEvent | CloudEvent |\n|---------|----------------|------------|\n| Standard | Azure-specific | CNCF standard |\n| Required fields | subject, eventType, dataVersion, data | source, type |\n| Extensibility | Limited | Extension attributes |\n| Interoperability | Azure only | Cross-platform |\n\n## Best Practices\n\n1. **Use CloudEvents** — Prefer CloudEvents for new implementations (industry standard)\n2. **Batch events** — Send multiple events in one call for efficiency\n3. **Use Entra ID** — Prefer managed identity over access keys\n4. **Idempotent handlers** — Events may be delivered more than once\n5. **Set event TTL** — Configure time-to-live for namespace events\n6. **Handle partial failures** — Acknowledge\u002Frelease events individually\n7. **Use dead-letter** — Configure dead-letter for failed events\n8. **Validate schemas** — Validate event data before processing\n\n## Error Handling\n\n```csharp\nusing Azure;\n\ntry\n{\n    await client.SendEventAsync(cloudEvent);\n}\ncatch (RequestFailedException ex) when (ex.Status == 401)\n{\n    Console.WriteLine(\"Authentication failed - check credentials\");\n}\ncatch (RequestFailedException ex) when (ex.Status == 403)\n{\n    Console.WriteLine(\"Authorization failed - check RBAC permissions\");\n}\ncatch (RequestFailedException ex) when (ex.Status == 413)\n{\n    Console.WriteLine(\"Payload too large - max 1MB per event, 1MB total batch\");\n}\ncatch (RequestFailedException ex)\n{\n    Console.WriteLine($\"Event Grid error: {ex.Status} - {ex.Message}\");\n}\n```\n\n## Failover Pattern\n\n```csharp\ntry\n{\n    var primaryClient = new EventGridPublisherClient(primaryUri, primaryKey);\n    await primaryClient.SendEventsAsync(events);\n}\ncatch (RequestFailedException)\n{\n    \u002F\u002F Failover to secondary region\n    var secondaryClient = new EventGridPublisherClient(secondaryUri, secondaryKey);\n    await secondaryClient.SendEventsAsync(events);\n}\n```\n\n## Related SDKs\n\n| SDK | Purpose | Install |\n|-----|---------|---------|\n| `Azure.Messaging.EventGrid` | Topics\u002FDomains (this SDK) | `dotnet add package Azure.Messaging.EventGrid` |\n| `Azure.Messaging.EventGrid.Namespaces` | Pull delivery | `dotnet add package Azure.Messaging.EventGrid.Namespaces` |\n| `Azure.Identity` | Authentication | `dotnet add package Azure.Identity` |\n| `Microsoft.Azure.WebJobs.Extensions.EventGrid` | Azure Functions trigger | `dotnet add package Microsoft.Azure.WebJobs.Extensions.EventGrid` |\n\n## Reference Links\n\n| Resource | URL |\n|----------|-----|\n| NuGet Package | https:\u002F\u002Fwww.nuget.org\u002Fpackages\u002FAzure.Messaging.EventGrid |\n| API Reference | https:\u002F\u002Flearn.microsoft.com\u002Fdotnet\u002Fapi\u002Fazure.messaging.eventgrid |\n| Quickstart | https:\u002F\u002Flearn.microsoft.com\u002Fazure\u002Fevent-grid\u002Fcustom-event-quickstart |\n| Pull Delivery | https:\u002F\u002Flearn.microsoft.com\u002Fazure\u002Fevent-grid\u002Fpull-delivery-overview |\n| GitHub Source | https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-sdk-for-net\u002Ftree\u002Fmain\u002Fsdk\u002Feventgrid\u002FAzure.Messaging.EventGrid |\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,134,688,"2026-05-16 13:06:13",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"DevOps","devops","mdi-cog-outline","CI\u002FCD、容器化、部署运维",3,162,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"429814f3-a416-49e9-b27d-0dfb6a64e0b7","1.0.0","azure-eventgrid-dotnet.zip",4158,"uploads\u002Fskills\u002F81e7e0f7-3dd4-47ed-8b7d-7c72a8ac6176\u002Fazure-eventgrid-dotnet.zip","a3cfbb19600e39f9e58231bfe330e30124871c320d509993cbf2ed5b366e0097","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":13571}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]