Azure.Messaging.EventGrid (.NET)
Bibliothèque cliente pour publier des événements vers les rubriques, domaines et namespaces Azure Event Grid.
Installation
# Pour les rubriques et domaines (livraison push)
dotnet add package Azure.Messaging.EventGrid
# Pour les namespaces (livraison pull)
dotnet add package Azure.Messaging.EventGrid.Namespaces
# Pour l'interopérabilité CloudNative CloudEvents
dotnet add package Microsoft.Azure.Messaging.EventGrid.CloudNativeCloudEvents
Version actuelle : 4.28.0 (stable)
Variables d'environnement
# Point de terminaison rubrique/domaine
EVENT_GRID_TOPIC_ENDPOINT=https://<topic-name>.<region>.eventgrid.azure.net/api/events
EVENT_GRID_TOPIC_KEY=<access-key>
# Point de terminaison namespace (pour la livraison pull)
EVENT_GRID_NAMESPACE_ENDPOINT=https://<namespace>.<region>.eventgrid.azure.net
EVENT_GRID_TOPIC_NAME=<topic-name>
EVENT_GRID_SUBSCRIPTION_NAME=<subscription-name>
Hiérarchie des clients
Livraison push (rubriques/domaines)
└── EventGridPublisherClient
├── SendEventAsync(EventGridEvent)
├── SendEventsAsync(IEnumerable<EventGridEvent>)
├── SendEventAsync(CloudEvent)
└── SendEventsAsync(IEnumerable<CloudEvent>)
Livraison pull (namespaces)
├── EventGridSenderClient
│ └── SendAsync(CloudEvent)
└── EventGridReceiverClient
├── ReceiveAsync()
├── AcknowledgeAsync()
├── ReleaseAsync()
└── RejectAsync()
Authentification
Authentification par clé API
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 (recommandé)
using Azure.Identity;
using Azure.Messaging.EventGrid;
EventGridPublisherClient client = new(
new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"),
new DefaultAzureCredential());
Authentification par jeton SAS
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);
Publication d'événements
Schéma EventGridEvent
EventGridPublisherClient client = new(
new Uri(topicEndpoint),
new AzureKeyCredential(topicKey));
// Événement unique
EventGridEvent egEvent = new(
subject: "orders/12345",
eventType: "Order.Created",
dataVersion: "1.0",
data: new { OrderId = "12345", Amount = 99.99 });
await client.SendEventAsync(egEvent);
// Lot d'événements
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);
Schéma CloudEvent
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);
// Lot de 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);
Publication vers un domaine Event Grid
// Les événements doivent spécifier la propriété Topic pour le routage du domaine
List<EventGridEvent> events = new()
{
new EventGridEvent(
subject: "orders/12345",
eventType: "Order.Created",
dataVersion: "1.0",
data: new { OrderId = "12345" })
{
Topic = "orders-topic" // Nom de la rubrique du domaine
},
new EventGridEvent(
subject: "inventory/item-1",
eventType: "Inventory.Updated",
dataVersion: "1.0",
data: new { ItemId = "item-1" })
{
Topic = "inventory-topic"
}
};
await client.SendEventsAsync(events);
Sérialisation personnalisée
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);
Livraison pull (namespaces)
Envoyer des événements vers une rubrique namespace
using Azure;
using Azure.Messaging;
using Azure.Messaging.EventGrid.Namespaces;
var senderClient = new EventGridSenderClient(
new Uri(namespaceEndpoint),
topicName,
new AzureKeyCredential(topicKey));
// Envoyer un événement unique
CloudEvent cloudEvent = new("employee_source", "Employee.Created",
new { Name = "John", Age = 30 });
await senderClient.SendAsync(cloudEvent);
// Envoyer un lot
await senderClient.SendAsync(new[]
{
new CloudEvent("source", "type", new { Name = "Alice" }),
new CloudEvent("source", "type", new { Name = "Bob" })
});
Recevoir et traiter les événements
var receiverClient = new EventGridReceiverClient(
new Uri(namespaceEndpoint),
topicName,
subscriptionName,
new AzureKeyCredential(topicKey));
// Recevoir les événements
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
{
// Traiter l'événement
Console.WriteLine($"Event: {cloudEvent.Type}, Data: {cloudEvent.Data}");
lockTokensToAck.Add(lockToken);
}
catch (Exception)
{
// Libérer pour réessai
lockTokensToRelease.Add(lockToken);
}
}
// Confirmer les événements traités avec succès
if (lockTokensToAck.Any())
{
await receiverClient.AcknowledgeAsync(lockTokensToAck);
}
// Libérer les événements pour réessai
if (lockTokensToRelease.Any())
{
await receiverClient.ReleaseAsync(lockTokensToRelease);
}
Rejeter les événements (Dead Letter)
// Rejeter les événements qui ne peuvent pas être traités
await receiverClient.RejectAsync(new[] { lockToken });
Consommer les événements (Azure Functions)
Déclencheur EventGridEvent
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}");
}
}
Déclencheur CloudEvent
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}");
}
}
Analyser les événements
Analyser EventGridEvent
// À partir d'une chaîne JSON
string json = "..."; // Charge utile webhook Event Grid
EventGridEvent[] events = EventGridEvent.ParseMany(BinaryData.FromString(json));
foreach (EventGridEvent egEvent in events)
{
if (egEvent.TryGetSystemEventData(out object systemEvent))
{
// Gérer l'événement système
switch (systemEvent)
{
case StorageBlobCreatedEventData blobCreated:
Console.WriteLine($"Blob created: {blobCreated.Url}");
break;
}
}
else
{
// Gérer l'événement personnalisé
var customData = egEvent.Data.ToObjectFromJson<MyCustomData>();
}
}
Analyser 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}");
}
Événements système
// Types d'événements système courants
using Azure.Messaging.EventGrid.SystemEvents;
// Événements de stockage
StorageBlobCreatedEventData blobCreated;
StorageBlobDeletedEventData blobDeleted;
// Événements de ressources
ResourceWriteSuccessEventData resourceCreated;
ResourceDeleteSuccessEventData resourceDeleted;
// Événements App Service
WebAppUpdatedEventData webAppUpdated;
// Événements Container Registry
ContainerRegistryImagePushedEventData imagePushed;
// Événements IoT Hub
IotHubDeviceCreatedEventData deviceCreated;
Référence des types clés
| Type |
Objectif |
EventGridPublisherClient |
Publier vers les rubriques/domaines |
EventGridSenderClient |
Envoyer vers les rubriques namespace |
EventGridReceiverClient |
Recevoir depuis les abonnements namespace |
EventGridEvent |
Schéma natif Event Grid |
CloudEvent |
Schéma CloudEvents 1.0 |
ReceiveResult |
Réponse de livraison pull |
ReceiveDetails |
Événement avec propriétés du courtier |
BrokerProperties |
Jeton de verrouillage, nombre de livraisons |
Comparaison des schémas d'événement
| Fonctionnalité |
EventGridEvent |
CloudEvent |
| Standard |
Spécifique à Azure |
Standard CNCF |
| Champs obligatoires |
subject, eventType, dataVersion, data |
source, type |
| Extensibilité |
Limitée |
Attributs d'extension |
| Interopérabilité |
Azure uniquement |
Inter-plateformes |
Bonnes pratiques
- Utiliser CloudEvents — Préférer CloudEvents pour les nouvelles implémentations (standard du secteur)
- Regrouper les événements — Envoyer plusieurs événements en un seul appel pour l'efficacité
- Utiliser Entra ID — Préférer l'identité managée aux clés d'accès
- Gestionnaires idempotents — Les événements peuvent être livrés plus d'une fois
- Définir un TTL d'événement — Configurer le time-to-live pour les événements namespace
- Gérer les défaillances partielles — Confirmer/libérer les événements individuellement
- Utiliser la dead-letter — Configurer la dead-letter pour les événements échoués
- Valider les schémas — Valider les données d'événement avant le traitement
Gestion des erreurs
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}");
}
Schéma de basculement
try
{
var primaryClient = new EventGridPublisherClient(primaryUri, primaryKey);
await primaryClient.SendEventsAsync(events);
}
catch (RequestFailedException)
{
// Basculer vers la région secondaire
var secondaryClient = new EventGridPublisherClient(secondaryUri, secondaryKey);
await secondaryClient.SendEventsAsync(events);
}
SDKs connexes
| SDK |
Objectif |
Installation |
Azure.Messaging.EventGrid |
Rubriques/domaines (ce SDK) |
dotnet add package Azure.Messaging.EventGrid |
Azure.Messaging.EventGrid.Namespaces |
Livraison pull |
dotnet add package Azure.Messaging.EventGrid.Namespaces |
Azure.Identity |
Authentification |
dotnet add package Azure.Identity |
Microsoft.Azure.WebJobs.Extensions.EventGrid |
Déclencheur Azure Functions |
dotnet add package Microsoft.Azure.WebJobs.Extensions.EventGrid |
Liens de référence