azure-eventgrid-dotnet について
azure-eventgrid-dotnet は、Azure Event Grid のイベントを送受信する .NET クライアント SDK です。イベント駆動型アプリケーションを開発する人向けで、トピックとドメインへのプッシュ配信、名前空間でのプル配信、EventGridEvent と CloudEvent の形式に対応します。
主な機能
- 01トピックとドメインへのイベント発行
- 02名前空間イベントの送受信
- 03EventGridEvent と CloudEvent 対応
- 04バッチ送信とイベント解析
- 05API キー、SAS、Microsoft Entra ID 認証
活用シーン
- 01Event Grid トピックへの業務イベント発行
- 02名前空間サブスクリプションからのイベント受信・処理
- 03Webhook ペイロードや CloudEvents の解析
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill azure-eventgrid-dotnetインストール後、Claude Code で/azure-eventgrid-dotnetを入力して読み込まれたか確認します。
詳細
Azure.Messaging.EventGrid (.NET)
Azure Event Grid のトピック、ドメイン、名前空間にイベントを発行するためのクライアントライブラリです。
インストール
# 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
過去のサンプルのバージョン:4.28.0。互換性のある SDK/Functions パッケージを確認し、バージョンを固定してください。
環境変数
# 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()
認証
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(推奨)
using Azure.Identity;
using Azure.Messaging.EventGrid;
EventGridPublisherClient client = new(
new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"),
new DefaultAzureCredential());
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);
イベントの発行
EventGridEvent スキーマ
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 スキーマ
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);
Event Grid ドメインへの発行
// 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);
カスタムシリアル化
using System.Text.Json;
using Azure.Core.Serialization;
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);
プル配信(名前空間)
名前空間のトピックへのイベント送信
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" })
});
イベントの受信と処理
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
await ProcessEventIdempotentlyAsync(cloudEvent); // application helper; durable success before ack
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 that cannot be processed
await receiverClient.RejectAsync(new[] { lockToken });
イベントの使用(Azure Functions)
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}");
}
}
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}");
}
}
イベントの解析
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>();
}
}
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}");
}
システムイベント
// 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;
主要な型のリファレンス
| 型 | 用途 |
|---|---|
EventGridPublisherClient | トピック/ドメインへの発行 |
EventGridSenderClient | 名前空間のトピックへの送信 |
EventGridReceiverClient | 名前空間のサブスクリプションからの受信 |
EventGridEvent | Event Grid ネイティブスキーマ |
CloudEvent | CloudEvents 1.0 スキーマ |
ReceiveResult | プル配信の応答 |
ReceiveDetails | ブローカーのプロパティを含むイベント |
BrokerProperties | ロックトークン、配信回数 |
イベントスキーマの比較
| 機能 | EventGridEvent | CloudEvent |
|---|---|---|
| 標準 | Azure 固有 | CNCF 標準 |
| 必須フィールド | 選択した Event Grid スキーマを確認してください | specversion、id、source、type(SDK が一部を初期化する場合があります) |
| 拡張性 | 限定的 | 拡張属性 |
| 相互運用性 | Azure のみ | クロスプラットフォーム |
ベストプラクティス
- CloudEvents を使用する — 新規実装では CloudEvents を優先してください(業界標準)
- イベントをバッチ処理する — 効率化のため、1 回の呼び出しで複数のイベントを送信してください
- Entra ID を使用する — アクセスキーよりマネージド ID を優先してください
- 冪等なハンドラーを使用する — イベントは複数回配信される場合があります
- イベントの TTL を設定する — 名前空間のイベントに有効期間を設定してください
- 部分的な失敗を処理する — イベントを個別に確認または解放してください
- デッドレターを使用する — 失敗したイベント用にデッドレターを構成してください
- スキーマを検証する — 処理前にイベントデータを検証してください
エラー処理
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}");
}
フェイルオーバーパターン
try
{
var primaryClient = new EventGridPublisherClient(primaryUri, primaryKey);
await primaryClient.SendEventsAsync(events);
}
catch (RequestFailedException ex) when (ex.Status >= 500 || ex.Status == 408)
{
// Explicitly configured failover only; primary acceptance may be unknown.
// Failover to secondary region
var secondaryClient = new EventGridPublisherClient(secondaryUri, secondaryKey);
await secondaryClient.SendEventsAsync(events);
}
関連 SDK
| SDK | 用途 | インストール |
|---|---|---|
Azure.Messaging.EventGrid | トピック/ドメイン(この SDK) | dotnet add package Azure.Messaging.EventGrid |
Azure.Messaging.EventGrid.Namespaces | プル配信 | dotnet add package Azure.Messaging.EventGrid.Namespaces |
Azure.Identity | 認証 | dotnet add package Azure.Identity |
Microsoft.Azure.WebJobs.Extensions.EventGrid | Azure Functions トリガー | dotnet add package Microsoft.Azure.WebJobs.Extensions.EventGrid |
参考リンク
使用する場面
このスキルは、概要で説明されているワークフローまたはアクションを実行する場合に適用されます。
制限事項
- このスキルは、タスクが上記の説明にある範囲に明確に該当する場合にのみ使用してください。
- 出力を、環境固有の検証、テスト、専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認を求めてください。
スニペットは個別の断片であり、コンパイルされたアプリケーションではありません。実際のトピック入力スキーマ、エンドポイント、サブスクリプションモードを使用してください。Functions のインプロセス用と分離ワーカー用のインポート/パッケージを混在させないでください。イベントペイロードと SAS/ロックトークンがログに記録されないよう保護してください。イベントごとの確認応答の失敗とロックの期限切れを検証してください。デッドレター処理が構成されていない場合、拒否するとイベントが破棄されることがあります。リージョン間の発行では、受け入れられたイベントが重複する可能性があり、サブスクリプションは引き継がれず、順序も保証されません。安定したイベント ID を保持し、永続的に重複を排除してください。処理の前に、Webhook の認証、サブスクリプションチャレンジ、スキーマを検証してください。制限はトピック/名前空間の API によって異なるため、確認が必要です。