[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M69AMR1EFEWAQWSCMCBTEW8E":3,"skill-same:01M69AMR1EFEWAQWSCMCBTEW8E":71},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":52,"ownerHtmlUrl":53,"ownerBlogUrl":54,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M69AMR1EFEWAQWSCMCBTEW8E","azure-eventgrid-dotnet",null,"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. Triggers: \"Event Grid\", \"EventGridPublisherClient\", \"CloudEvent\", \"EventGridEvent\", \"publish events .NET\", \"event-driven\", \"pub\u002Fsub\".","microsoft\u002Fskills","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M69AJYYW4E1RMSYCQDJ4FJSH",3202,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fplugins\u002Fazure-sdk-dotnet\u002Fskills\u002Fazure-eventgrid-dotnet\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,9],"dotnet","azure","azure eventgrid dotnet","triggers","for","grid","with","event","azure event grid","event-driven","architectures","client","events","sdk","publishing","use","publish","library","messaging","2026-11-10 10:12:30",false,"---\nname: azure-eventgrid-dotnet\ndescription: |\n  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. Triggers: \"Event Grid\", \"EventGridPublisherClient\", \"CloudEvent\", \"EventGridEvent\", \"publish events .NET\", \"event-driven\", \"pub\u002Fsub\".\nlicense: MIT\nmetadata:\n  author: Microsoft\n  version: \"1.0.0\"\n  package: Azure.Messaging.EventGrid\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\nEVENT_GRID_TOPIC_ENDPOINT=https:\u002F\u002F\u003Ctopic-name>.\u003Cregion>.eventgrid.azure.net\u002Fapi\u002Fevents  # Required: Event Grid topic or domain endpoint\nEVENT_GRID_TOPIC_KEY=\u003Caccess-key>  # Only required for AzureKeyCredential auth\nEVENT_GRID_NAMESPACE_ENDPOINT=https:\u002F\u002F\u003Cnamespace>.\u003Cregion>.eventgrid.azure.net  # Optional: Event Grid namespace endpoint\nEVENT_GRID_TOPIC_NAME=\u003Ctopic-name>  # Required: Event Grid topic name\nEVENT_GRID_SUBSCRIPTION_NAME=\u003Csubscription-name>  # Optional: Event Grid subscription name\nAZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production\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 Token Credential\n\n```csharp\nusing Azure.Identity;\nusing Azure.Messaging.EventGrid;\n\n\u002F\u002F Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=\u003Cspecific_credential>\nvar credential = new DefaultAzureCredential(\n    DefaultAzureCredential.DefaultEnvironmentVariableName\n);\n\u002F\u002F Or use a specific credential directly in production:\n\u002F\u002F See https:\u002F\u002Flearn.microsoft.com\u002Fdotnet\u002Fapi\u002Foverview\u002Fazure\u002Fidentity-readme?view=azure-dotnet#credential-classes\n\u002F\u002F var credential = new ManagedIdentityCredential();\nEventGridPublisherClient client = new(\n    new Uri(\"https:\u002F\u002Fmytopic.eastus-1.eventgrid.azure.net\u002Fapi\u002Fevents\"),\n    credential);\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","# 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\nEVENT_GRID_TOPIC_ENDPOINT=https:\u002F\u002F\u003Ctopic-name>.\u003Cregion>.eventgrid.azure.net\u002Fapi\u002Fevents  # Required: Event Grid topic or domain endpoint\nEVENT_GRID_TOPIC_KEY=\u003Caccess-key>  # Only required for AzureKeyCredential auth\nEVENT_GRID_NAMESPACE_ENDPOINT=https:\u002F\u002F\u003Cnamespace>.\u003Cregion>.eventgrid.azure.net  # Optional: Event Grid namespace endpoint\nEVENT_GRID_TOPIC_NAME=\u003Ctopic-name>  # Required: Event Grid topic name\nEVENT_GRID_SUBSCRIPTION_NAME=\u003Csubscription-name>  # Optional: Event Grid subscription name\nAZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production\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 Token Credential\n\n```csharp\nusing Azure.Identity;\nusing Azure.Messaging.EventGrid;\n\n\u002F\u002F Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=\u003Cspecific_credential>\nvar credential = new DefaultAzureCredential(\n    DefaultAzureCredential.DefaultEnvironmentVariableName\n);\n\u002F\u002F Or use a specific credential directly in production:\n\u002F\u002F See https:\u002F\u002Flearn.microsoft.com\u002Fdotnet\u002Fapi\u002Foverview\u002Fazure\u002Fidentity-readme?view=azure-dotnet#credential-classes\n\u002F\u002F var credential = new ManagedIdentityCredential();\nEventGridPublisherClient client = new(\n    new Uri(\"https:\u002F\u002Fmytopic.eastus-1.eventgrid.azure.net\u002Fapi\u002Fevents\"),\n    credential);\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",{"name":5,"license":15,"metadata":43,"description":46},{"author":12,"package":44,"version":45},"Azure.Messaging.EventGrid","1.0.0","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. Triggers: \"Event Grid\", \"EventGridPublisherClient\", \"CloudEvent\", \"EventGridEvent\", \"publish events .NET\", \"event-driven\", \"pub\u002Fsub\".\n","main","3f5b461b2314e01c400564051e92469114c5b68f",".github\u002Fplugins\u002Fazure-sdk-dotnet\u002Fskills\u002Fazure-eventgrid-dotnet",368,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills","https:\u002F\u002Fmicrosoft.github.io\u002Fskills\u002F","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-14 02:08:41",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add microsoft\u002Fskills --skill azure-eventgrid-dotnet",{"tool":63,"command":64},"bunx","bunx skills add microsoft\u002Fskills --skill azure-eventgrid-dotnet",{"tool":66,"command":67},"pnpm","pnpm dlx skills add microsoft\u002Fskills --skill azure-eventgrid-dotnet","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fplugins\u002Fazure-sdk-dotnet\u002Fskills\u002Fazure-eventgrid-dotnet\u002FSKILL.md",true,[],[72,98,136,163,183,221],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":83,"publishedAt":38},"01M69B4JCRQV5SPXAFCKXQRV0H","skill-creator","Guide for creating effective skills for AI coding agents working with Azure SDKs and Microsoft Foundry services. Use when creating new skills or updating existing skills.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fskill-creator\u002FSKILL.md",[78],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[84,85,86,9,87,88,89,20,90,91,92,34,93,25,94,23,95,96,97],"skill creator","creator","coding agents","foundry","microsoft foundry","ai coding agents","services","coding","guide","ai coding","sdks","Existing","when","new",{"skillNo":99,"name":100,"nameZh":6,"description":101,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":102,"categories":103,"keywords":114,"publishedAt":38},"01M69B4FD57V1MYKRWAJJECTZ7","podcast-generation","Generate AI-powered podcast-style audio narratives using Azure OpenAI's GPT Realtime Mini model via WebSocket. Use when building text-to-speech features, audio narrative generation, podcast creation from content, or integrating with Azure OpenAI Realtime API for real audio output. Covers full-stack implementation from React frontend to Python FastAPI backend with WebSocket streaming.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fpodcast-generation\u002FSKILL.md",[104,107,110,113],{"categoryNo":105,"categoryName":106,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":108,"categoryName":109,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":111,"categoryName":112,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},[115,116,117,118,119,120,121,20,122,123,124,125,126,127,128,129,130,131,132,133,134,96,135],"podcast generation","podcast","generation","frontend","python","react","realtime","azure openai","generate","streaming","api","Audio","stack","text","model","fastapi","creation","python fastapi","narrative","features","fastapi backend",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":143,"publishedAt":38},"01M69B4CYPM5SESY5ZWEFDXEQZ","microsoft-docs","Understand Microsoft technologies by querying official documentation. Use whenever the user asks how something works, wants tutorials, needs configuration options, limits, quotas, or best practices for any Microsoft technology (Azure, .NET, M365, Windows, Power Platform, etc.)—even if they don't mention \"docs.\" If the question is about understanding a concept rather than writing code, this is the right skill.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fmicrosoft-docs\u002FSKILL.md",[142],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},[144,9,145,146,147,148,149,150,151,152,153,20,154,155,156,34,157,60,158,159,160,161,162,23],"docs","microsoft docs","MCP","writing","cli","mcp server","windows","power platform","official","documentation","learn","best practices","question","power","back","technology","platform","learn mcp","concept",{"skillNo":164,"name":165,"nameZh":6,"description":166,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":167,"categories":168,"keywords":170,"publishedAt":38},"01M69B49C3YPD1ZJ3NC0HPCY58","mcp-builder","Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP), Node\u002FTypeScript (MCP SDK), or C#\u002F.NET (Microsoft MCP SDK).","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fmcp-builder\u002FSKILL.md",[169],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},[146,171,172,173,119,174,32,175,9,176,177,129,178,179,92,34,180,181,182,25,23,96],"mcp builder","builder","typescript","llms","model context protocol","fastmcp","Tools","node","context","integrate","mcp sdk","building mcp servers",{"skillNo":184,"name":185,"nameZh":6,"description":186,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":187,"categories":188,"keywords":201,"publishedAt":38},"01M69B467A7CDMFQ0T6Q0ZA12Q","kql","KQL language expertise for writing correct, efficient Kusto Query Language queries. Covers syntax gotchas, join patterns, dynamic types, datetime pitfalls, regex patterns, serialization, memory management, result-size discipline, and advanced functions (geo, vector, graph). USE THIS SKILL whenever writing, debugging, or reviewing KQL queries — even simple ones — because the gotchas section prevents the most common errors that waste tool calls and cause expensive retry cascades. Trigger on: KQL, Kusto, ADX, Azure Data Explorer, Fabric Real-Time Intelligence, EventHouse, Log Analytics, log analysis, data exploration, time series, anomaly detection, summarize, where clause, join, extend, project, let statement, parse operator, extract function, any mention of pipe-forward query syntax.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fkql\u002FSKILL.md",[189,192,193,198],{"categoryNo":190,"categoryName":191,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},{"categoryNo":194,"categoryName":195,"taxonomyType":196,"taxonomyTypeDesc":197},"01JBSEEDCAT000000000000033","数据分析师","PROFESSION","适用职业",{"categoryNo":199,"categoryName":200,"taxonomyType":196,"taxonomyTypeDesc":197},"01JBSEEDCAT000000000000036","内容创作者",[185,147,202,203,204,20,205,206,207,208,209,210,211,212,213,214,215,216,217,23,218,219,220],"summarize","memory","analytics","vector","time series","tool","discipline","log","geo","exploration","pipe","time","project","regex","join","datetime","section","anomaly","parse",{"skillNo":222,"name":223,"nameZh":6,"description":224,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":225,"categories":226,"keywords":227,"publishedAt":38},"01M69B44HJQ7897EZ7NE7DWQX3","github-issue-creator","Convert raw notes, error logs, voice dictation, or screenshots into crisp GitHub-flavored markdown issue reports. Use when the user pastes bug info, error messages, or informal descriptions and wants a structured GitHub issue. Supports images\u002FGIFs for visual evidence.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fgithub-issue-creator\u002FSKILL.md",[],[228,229,230,231,85,232,233,234,235,236,237,238,34,239,240,241,242,243,244,23,96],"github","github issue creator","github issue","issue","issue creator","screenshots","notes","logs","error messages","messages","convert","evidence","reports","images","info","visual","error"]