diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/README.md b/sdk/eventgrid/Azure.Messaging.EventGrid/README.md index ee09ff807c4b0..8d7546473b743 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/README.md +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/README.md @@ -41,13 +41,13 @@ az eventgrid topic key list --name --resource-group ", new AzureKeyCredential("")); ``` You can also create a **Shared Access Signature** to authenticate the client using the same access key. The signature can be generated using the endpoint, access key, and the time at which the signature becomes invalid for authentication. Create the client using the `EventGridSharedAccessSignatureCredential` type: -```csharp +```C# string sasToken = EventGridPublisherClient.BuildSharedAccessSignature( "", DateTimeOffset.UtcNow.AddMinutes(60), @@ -76,7 +76,7 @@ While you may configure your topic to use a custom schema, it is more common to #### CloudEvents v1.0 schema Another option is to use the CloudEvents v1.0 schema. [CloudEvents](https://cloudevents.io/) is a Cloud Native Computing Foundation project which produces a specification for describing event data in a common way. The service summary of CloudEvents can be found [here](https://docs.microsoft.com/en-us/azure/event-grid/cloud-event-schema). -Regardless of what schema your topic or domain is configured to use, `EventGridPublisherClient` will be used to publish events to it. +Regardless of what schema your topic or domain is configured to use, `EventGridPublisherClient` will be used to publish events to it. Use the `SendEvents` or `SendEventsAsync` method for publishing. ### Event delivery Events delivered to consumers by Event Grid are *delivered as JSON*. Depending on the type of consumer being delivered to, the Event Grid service may deliver one or more events as part of a single payload. Handling events will be different based on which schema the event was delivered as. However, the general pattern will remain the same: @@ -90,8 +90,8 @@ Events delivered to consumers by Event Grid are *delivered as JSON*. Depending o * [Receiving and Deserializing Events](#receiving-and-deserializing-events) ### Publish Event Grid events to an Event Grid Topic -Publishing events to Event Grid is performed using the `EventGridPublisherClient`. Use the provided `SendEvents` method to publish events to the topic. -```csharp Snippet:SendEGEventsToTopic +Publishing events to Event Grid is performed using the `EventGridPublisherClient`. Use the provided `SendEvents`/`SendEventsAsync` method to publish events to the topic. +```C# Snippet:SendEGEventsToTopic // Add EventGridEvents to a list to publish to the topic List eventsList = new List { @@ -106,8 +106,8 @@ List eventsList = new List await client.SendEventsAsync(eventsList); ``` ### Publish CloudEvents to an Event Grid Topic -Publishing events to Event Grid is performed using the `EventGridPublisherClient`. Use the provided `SendEvents` method to publish events to the topic. -```csharp Snippet:SendCloudEventsToTopic +Publishing events to Event Grid is performed using the `EventGridPublisherClient`. Use the provided `SendEvents`/`SendEventsAsync` method to publish events to the topic. +```C# Snippet:SendCloudEventsToTopic // Add CloudEvents to a list to publish to the topic List eventsList = new List { @@ -122,7 +122,7 @@ List eventsList = new List "/cloudevents/example/binarydata", "Example.EventType", new BinaryData("This is binary data"), - "example/binary")}; + "example/binary")}; // Send the events await client.SendEventsAsync(eventsList); @@ -132,7 +132,7 @@ await client.SendEventsAsync(eventsList); An **event domain** is a management tool for large numbers of Event Grid topics related to the same application. You can think of it as a meta-topic that can have thousands of individual topics. When you create an event domain, you're given a publishing endpoint similar to if you had created a topic in Event Grid. To publish events to any topic in an Event Domain, push the events to the domain's endpoint the same way you would for a custom topic. The only difference is that you must specify the topic you'd like the event to be delivered to. -```csharp Snippet:SendEventsToDomain +```C# Snippet:SendEventsToDomain // Add EventGridEvents to a list to publish to the domain // Don't forget to specify the topic you want the event to be delivered to! List eventsList = new List @@ -154,24 +154,47 @@ await client.SendEventsAsync(eventsList); ### Receiving and Deserializing Events There are several different Azure services that act as [event handlers](https://docs.microsoft.com/en-us/azure/event-grid/event-handlers). -Note: if using Webhooks to for event delivery, Event Grid requires you to prove ownership of your Webhook endpoint before it starts delivering events to that endpoint. At the time of event subscription creation, Event Grid sends a subscription validation event to your endpoint, as seen below. Learn more about completing the handshake here: [Webhook event delivery](https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery) +Note: if using Webhooks for event delivery of the *Event Grid schema*, Event Grid requires you to prove ownership of your Webhook endpoint before it starts delivering events to that endpoint. At the time of event subscription creation, Event Grid sends a subscription validation event to your endpoint, as seen below. Learn more about completing the handshake here: [Webhook event delivery](https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery). For the *CloudEvents schema*, the service validates the connection using the HTTP options method. Learn more here: [CloudEvents validation](https://github.com/cloudevents/spec/blob/v1.0/http-webhook.md#4-abuse-protection). Once events are delivered to the event handler, parse the JSON payload into list of events. Using `EventGridEvent`: -```csharp Snippet:EgEventParseJson +```C# Snippet:EGEventParseJson // Parse the JSON payload into a list of events using EventGridEvent.Parse EventGridEvent[] egEvents = EventGridEvent.Parse(jsonPayloadSampleOne); ``` Using `CloudEvent`: -```csharp Snippet:CloudEventParseJson +```C# Snippet:CloudEventParseJson // Parse the JSON payload into a list of events using CloudEvent.Parse CloudEvent[] cloudEvents = CloudEvent.Parse(jsonPayloadSampleTwo); ``` -From here, one can access the event data by deserializing to a specific type using `GetData()` and passing in a custom serializer if necessary. Calling `GetData()` will either return a deserialized **system event** (an event generated by an Azure service), or an object of type `BinaryData`, which represents the serialized JSON event data as bytes. Below is an example calling `GetData()`: - -```csharp Snippet:DeserializePayloadUsingNonGenericGetData +From here, one can access the event data by deserializing to a specific type using `GetData()` and passing in a custom serializer if necessary. Below is an example calling `GetData()` using CloudEvents. In order to deserialize to the correct type, the `EventType` property (`Type` for CloudEvents) helps distinguish between different events. +```C# Snippet:DeserializePayloadUsingGenericGetData +foreach (CloudEvent cloudEvent in cloudEvents) +{ + switch (cloudEvent.Type) + { + case "Contoso.Items.ItemReceived": + // By default, GetData uses JsonObjectSerializer to deserialize the payload + ContosoItemReceivedEventData itemReceived = cloudEvent.GetData(); + Console.WriteLine(itemReceived.ItemSku); + break; + case "MyApp.Models.CustomEventType": + // One can also specify a custom ObjectSerializer as needed to deserialize the payload correctly + TestPayload testPayload = await cloudEvent.GetDataAsync(myCustomSerializer); + Console.WriteLine(testPayload.Name); + break; + case "Microsoft.Storage.BlobDeleted": + // Example for deserializing system events using GetData + StorageBlobDeletedEventData blobDeleted = cloudEvent.GetData(); + Console.WriteLine(blobDeleted.BlobType); + break; + } +} +``` +Below is an example calling `GetData()` using Event Grid events. Calling `GetData()` will either return a deserialized **system event** (an event generated by an Azure service), or an object of type `BinaryData`, which represents the serialized JSON event data as bytes. +```C# Snippet:DeserializePayloadUsingNonGenericGetData foreach (EventGridEvent egEvent in egEvents) { // If the event is a system event, GetData() should return the correct system event type @@ -195,30 +218,6 @@ foreach (EventGridEvent egEvent in egEvents) } } ``` -Here is an example calling `GetData()` using CloudEvents. In order to deserialize to the correct type, the `EventType` property (`Type` for CloudEvents) helps distinguish between different events. -```csharp Snippet:DeserializePayloadUsingGenericGetData -foreach (CloudEvent cloudEvent in cloudEvents) -{ - switch (cloudEvent.Type) - { - case "Contoso.Items.ItemReceived": - // By default, GetData uses JsonObjectSerializer to deserialize the payload - ContosoItemReceivedEventData itemReceived = cloudEvent.GetData(); - Console.WriteLine(itemReceived.ItemSku); - break; - case "MyApp.Models.CustomEventType": - // One can also specify a custom ObjectSerializer as needed to deserialize the payload correctly - TestPayload testPayload = await cloudEvent.GetDataAsync(myCustomSerializer); - Console.WriteLine(testPayload.Name); - break; - case "Microsoft.Storage.BlobDeleted": - // Example for deserializing system events using GetData - StorageBlobDeletedEventData blobDeleted = cloudEvent.GetData(); - Console.WriteLine(blobDeleted.BlobType); - break; - } -} -``` ## Troubleshooting @@ -226,8 +225,7 @@ foreach (CloudEvent cloudEvent in cloudEvents) `SendEvents()` returns a HTTP response code from the service. A `RequestFailedException` is thrown as a service response for any unsuccessful requests. The exception contains information about what response code was returned from the service. ### Deserializing Event Data -- An `InvalidCastException` will be thrown during `GetData()` if the event data cannot be cast to the specified type. - +- If the event data is not valid JSON, a `JsonException` will be thrown during `Parse`. - An `InvalidOperationException` will be thrown during `GetData()` if a custom serializer is passed into `GetData()` with non-serialized event data (for example, if the event was created by the user and not created by parsing from JSON). ### Setting up console logging diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample1_PublishEventsToTopic.md b/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample1_PublishEventsToTopic.md index c374ccb1df356..f97024b4c594c 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample1_PublishEventsToTopic.md +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample1_PublishEventsToTopic.md @@ -6,14 +6,14 @@ To begin, create separate custom Event Grid topics accepting events of the Event ## Creating and Authenticating `EventGridPublisherClient` Once you have your access key and topic endpoint, you can create the publisher client using the `AzureKeyCredential` class as follows: -```csharp Snippet:CreateClient +```C# Snippet:CreateClient EventGridPublisherClient client = new EventGridPublisherClient( new Uri(topicEndpoint), new AzureKeyCredential(topicAccessKey)); ``` `EventGridPublisherClient` also accepts a set of configuring options through `EventGridPublisherClientOptions`. For example, specifying a custom serializer used to serialize the event data to JSON: -```csharp Snippet:CreateClientWithOptions +```C# Snippet:CreateClientWithOptions EventGridPublisherClientOptions clientOptions = new EventGridPublisherClientOptions() { DataSerializer = myCustomDataSerializer @@ -33,7 +33,7 @@ Following that, invoke `SendEvents` or `SendEventsAsync` to publish the events t Note on `EventGridEvent`: each `EventGridEvent` has a set of required, non-nullable properties, including event data. `EventTime` and `Id` are also required properties that are set by default, but can also be manually set if needed. -```csharp Snippet:SendEGEventsToTopic +```C# Snippet:SendEGEventsToTopic // Add EventGridEvents to a list to publish to the topic List eventsList = new List { @@ -55,7 +55,7 @@ Following that, invoke `SendEvents` or `SendEventsAsync` to publish the events t Note on `CloudEvent`: each `CloudEvent` has a set of required, non-nullable properties. However, `Data` is *not required*. `Time` and `SpecVersion` are required properties that are set by default, but can also be manually set if needed. `Time` is also set by default, but not required. -```csharp Snippet:SendCloudEventsToTopic +```C# Snippet:SendCloudEventsToTopic // Add CloudEvents to a list to publish to the topic List eventsList = new List { diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample2_PublishEventsToDomain.md b/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample2_PublishEventsToDomain.md index 21377b181f613..416e540994c3c 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample2_PublishEventsToDomain.md +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample2_PublishEventsToDomain.md @@ -11,7 +11,7 @@ See the this [step-by-step tutorial](https://docs.microsoft.com/en-us/azure/even ## Create and Authenticate `EventGridPublisherClient` If you have not created an `EventGridPublisherClient`, refer to the sample [Publish Events To Topic](Sample1_PublishEventsToTopic.md) for more information on creating and authenticating the client. An example is shown below: -```csharp Snippet:CreateDomainClient +```C# Snippet:CreateDomainClient // Create the publisher client using an AzureKeyCredential // Domain should be configured to accept events of the Event Grid schema EventGridPublisherClient client = new EventGridPublisherClient( @@ -22,7 +22,7 @@ EventGridPublisherClient client = new EventGridPublisherClient( ## Publish Events to Azure Event Grid To publish events to any topic in an Event Domain, push the events to the domain's endpoint the same way you would for a custom topic. The only difference is that you must specify the topic you'd like the event to be delivered to. Invoke `SendEvents` or `SendEventsAsync` to publish events to the service. -```csharp Snippet:SendEventsToDomain +```C# Snippet:SendEventsToDomain // Add EventGridEvents to a list to publish to the domain // Don't forget to specify the topic you want the event to be delivered to! List eventsList = new List diff --git a/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample3_ParseAndDeserializeEvents.md b/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample3_ParseAndDeserializeEvents.md index e2c2ba1d62055..89cb954baf346 100644 --- a/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample3_ParseAndDeserializeEvents.md +++ b/sdk/eventgrid/Azure.Messaging.EventGrid/samples/Sample3_ParseAndDeserializeEvents.md @@ -2,7 +2,7 @@ This sample will demonstrate how to deserialize events that have been delivered to event handlers. There are several different Azure services that act as [event handlers](https://docs.microsoft.com/en-us/azure/event-grid/event-handlers). Regardless of the event handler, however, events are always sent as UTF-8 encoded JSON. -Note: if using Webhooks to for event delivery, Event Grid requires you to prove ownership of your Webhook endpoint before it starts delivering events to that endpoint. At the time of event subscription creation, Event Grid sends a subscription validation event to your endpoint, as seen below. Learn more about completing the handshake here: [Webhook event delivery](https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery) +Note: if using Webhooks for event delivery of the *Event Grid schema*, Event Grid requires you to prove ownership of your Webhook endpoint before it starts delivering events to that endpoint. At the time of event subscription creation, Event Grid sends a subscription validation event to your endpoint, as seen below. Learn more about completing the handshake here: [Webhook event delivery](https://docs.microsoft.com/en-us/azure/event-grid/webhook-event-delivery). For the *CloudEvents schema*, the service validates the connection using the HTTP options method. Learn more here: [CloudEvents validation](https://github.com/cloudevents/spec/blob/v1.0/http-webhook.md#4-abuse-protection). Handling events will be different based on which schema the event was delivered as. However, the general pattern will remain the same: - Parse events from JSON into individual events. Based on the event schema (Event Grid or CloudEvents 1.0), you can now access basic information about the event on the envelope (properties that are present for all events, like event time and type). @@ -12,24 +12,50 @@ Handling events will be different based on which schema the event was delivered Once events are delivered to the event handler, parse the JSON payload into list of events. Using `EventGridEvent`: -```csharp Snippet:EgEventParseJson +```C# Snippet:EGEventParseJson // Parse the JSON payload into a list of events using EventGridEvent.Parse EventGridEvent[] egEvents = EventGridEvent.Parse(jsonPayloadSampleOne); ``` Using `CloudEvent`: -```csharp Snippet:CloudEventParseJson +```C# Snippet:CloudEventParseJson // Parse the JSON payload into a list of events using CloudEvent.Parse CloudEvent[] cloudEvents = CloudEvent.Parse(jsonPayloadSampleTwo); ``` ## Deserialize Event Data From here, one can access the event data by deserializing to a specific type using `GetData()` and passing in a custom serializer if necessary. Calling `GetData()` will either return a deserialized system event (an event generated by an Azure service), or the event data wrapped in `BinaryData`, which represents the serialized JSON event data as bytes. +### Using `GetData()` +Below is an example calling `GetData()` for CloudEvents. In order to deserialize to the correct type, the `EventType` property (`Type` for CloudEvents) helps distinguish between different events. Custom event data should be deserialized using the generic method `GetData()`. There is also an overload for `GetData()` that accepts a custom `ObjectSerializer` to deserialize the event data. + +```C# Snippet:DeserializePayloadUsingGenericGetData +foreach (CloudEvent cloudEvent in cloudEvents) +{ + switch (cloudEvent.Type) + { + case "Contoso.Items.ItemReceived": + // By default, GetData uses JsonObjectSerializer to deserialize the payload + ContosoItemReceivedEventData itemReceived = cloudEvent.GetData(); + Console.WriteLine(itemReceived.ItemSku); + break; + case "MyApp.Models.CustomEventType": + // One can also specify a custom ObjectSerializer as needed to deserialize the payload correctly + TestPayload testPayload = await cloudEvent.GetDataAsync(myCustomSerializer); + Console.WriteLine(testPayload.Name); + break; + case "Microsoft.Storage.BlobDeleted": + // Example for deserializing system events using GetData + StorageBlobDeletedEventData blobDeleted = cloudEvent.GetData(); + Console.WriteLine(blobDeleted.BlobType); + break; + } +} +``` ### Using `GetData()` If expecting mostly system events, it may be cleaner to switch on object `GetData()` and use pattern matching to deserialize events. In the case where there are unrecognized event types, one can use the returned `BinaryData` to deserialize the custom event data. -```csharp Snippet:DeserializePayloadUsingNonGenericGetData +```C# Snippet:DeserializePayloadUsingNonGenericGetData foreach (EventGridEvent egEvent in egEvents) { // If the event is a system event, GetData() should return the correct system event type @@ -53,31 +79,6 @@ foreach (EventGridEvent egEvent in egEvents) } } ``` -### Using `GetData()` -Below is an example calling `GetData()` for CloudEvents. In order to deserialize to the correct type, the `EventType` property (`Type` for CloudEvents) helps distinguish between different events. Custom event data should be deserialized using the generic method `GetData()`. There is also an overload for `GetData()` that accepts a custom `ObjectSerializer` to deserialize the event data. - -```csharp Snippet:DeserializePayloadUsingGenericGetData -foreach (CloudEvent cloudEvent in cloudEvents) -{ - switch (cloudEvent.Type) - { - case "Contoso.Items.ItemReceived": - // By default, GetData uses JsonObjectSerializer to deserialize the payload - ContosoItemReceivedEventData itemReceived = cloudEvent.GetData(); - Console.WriteLine(itemReceived.ItemSku); - break; - case "MyApp.Models.CustomEventType": - // One can also specify a custom ObjectSerializer as needed to deserialize the payload correctly - TestPayload testPayload = await cloudEvent.GetDataAsync(myCustomSerializer); - Console.WriteLine(testPayload.Name); - break; - case "Microsoft.EventGrid.SubscriptionValidationEvent": - SubscriptionValidationEventData subscriptionValidated = cloudEvent.GetData(); - Console.WriteLine(subscriptionValidated.ValidationCode); - break; - } -} -``` ## Source To view the full example source, see: