CHAPTER 5
In the previous chapter, we looked at Azure Service Bus, a messaging as a service offering in the Azure ecosystem. Before that, we looked at the Azure Logic Apps and Azure Functions services. Azure Event Grid routes events from one source to the next, at massive scale. These events can come from various sources, such as storage accounts or subscriptions, and can be routed to various targets, like an Azure function, a logic app, or a Service Bus queue. Event Grid works with subscriptions, topics, and domains.
No matter what kind of Event Grid resource you create, you’ll never have to specify a pricing plan. With Event Grid, like with all serverless offerings, you pay for usage. The first 100,000 operations a month are free of charge. After that, you pay €0.506 per million operations. For most small and medium-sized applications, that means free to 50 cents a month. Don’t underestimate the number of events you’ll generate, though. I recently created a small app that reacted to a daily export of a third-party application. The application generated a new event, which would then be handled, and that was it. It turned out to be about 800 events from the export per day in a 20-day month, or 20 * 800 * 2, which adds up to 32,000 events a month. And that’s just one small application. That’s still free, but it quickly adds up. The following demos will be free in any case.
Event Grid works a little different than other Azure resources. You don’t create an event grid like you’d create a web app, for example. Instead, you create event subscriptions, topics, and domains. Subscriptions are at the base of Event Grid. You can create Event Grid subscriptions in two ways. First, go to all services and search for Event Grid. You’ll find Event Grid domains, subscriptions, and topics. Select Subscriptions there and click + Event Subscription at the top. This will take you to the creation blade where you can pick your subscription details, including topics, events, and endpoints (event handlers).
There is a second way to create subscriptions. You can browse to whatever resource you want events from and create it there. This works, for example, for subscriptions, resource groups, storage accounts (either general-purpose v2 or blob storage), Key Vault (currently in preview), and Service Bus (Premium). For other resources, read the documentation.
Let’s pick an example that we’re familiar with: we’re going to get events from a storage account to a Service Bus queue. So, go to a (general-purpose v2) storage account and select Events in the menu. Alternatively, create a subscription from the Event Subscriptions Overview page. For this demo, we’re using the storage account. A Get Started page appears, which already gives you some options for creating a subscription with an event handler. The default is a logic app that triggers when a blob is uploaded, but you can also choose when an image or video is uploaded. The Azure Function option just takes you to your functions overview. Under More Options you can also see Web Hook, Storage Queues, Event Hubs, Hybrid Connections, Service Bus Queue, and Service Bus Topic. All these buttons currently do the same thing, which is what also happens when you click + Event Subscription at the top: you get a subscription creation blade for the storage account topic, and no endpoint details (event handler).

Figure 31: Subscription Event Handlers
In the creation blade, enter a name for your subscription. The topic type and resource are already filled out, which are Storage account and the storage account that you selected. You can filter some event types. The events Blob Created and Blob Deleted are selected by default, but there’s also a Blob Renamed event, and those same events exist for directories.
The endpoint type is the event handler, and we’ve already seen those. Select the Service Bus queue type and then select the endpoint. You can only select an existing queue, so if you don’t want to use a queue that we’ve used in the previous examples, you should create a new queue first.
The Event Schema property needs a little more explanation. If an event is triggered, you’ll receive event data. The data received and the format of the data depend on the event schema. The default is the Event Grid Schema, which contains data such as the Azure tenant and subscription, authorization information, and claims. This data is not very useful for our example. Instead, select Cloud Event Schema v1.0, which contains the type of event, a link to the created or deleted blob, the content type, the length of the blob, and the eTag that uniquely identifies a blob. Next to the basic subscription information, you can add additional filters and features, such as specific storage containers, dead-lettering, and retry policies. You can add or change these options later.

Figure 32: Creating an Event Subscription
Click Create, and your topic and subscription are created. If you now look at the Events blade in your storage account, you can see the event subscription. If you remember, we saw event subscriptions under all resources, too. However, you won’t see your subscription there because of the default filter. It makes little sense, but you need to select your Topic Type (Storage Accounts), your Subscription, and your Location before you see anything. When you change the filter, your subscription is there, though.
Let’s see our subscription in action. Simply go to your storage account and upload a file. Now, connect to your queue using Service Bus Explorer and read your queue. You should see a message with text that looks like the following.
Code Listing 37
{ "id": "036490ca-801e-001f-35f3-dcf675062001", "source": "/subscriptions/[…]/storageAccounts/storageaccountsuccia377", "specversion": "1.0", "type": "Microsoft.Storage.BlobCreated", "dataschema": "#", "subject": "/blobServices/default/containers/mycontainer/blobs/dummy.txt", "time": "2020-02-06T13:45:04.2806789Z", "data": { "api": "PutBlockList", "clientRequestId": "ab9f3d2b-410c-4f48-903e-b43d11028067", "requestId": "036490ca-801e-001f-35f3-dcf675000000", "eTag": "0x8D7AB0AC5333D0B", "contentType": "text/plain", "contentLength": 19, "blobType": "BlockBlob", "url": […]/mycontainer/dummy.txt", "sequencer": "00000000000000000000000000003CFB00000000038b29d3", "storageDiagnostics": { "batchId": "d4c88382-9006-002c-00f3-dca9de000000" } } } |
The source and type properties are useful for filtering in applications that need to respond to events. The data object has more useful information, such as the URL and eTag. The subject is useful too, since you can filter based on subject. In my case, I have a container named mycontainer, and I really don’t want to get events from other containers. Go back to your event subscription and select Filters. Enable subject filtering and enter /blobServices/default/containers/mycontainer in Subject Begins With to only get events for mycontainer. There’s also a Subject Ends With filter, which is useful if you want to filter for specific file types.
Note: Do you get a lot of events from your storage account? If you have an Azure function that’s triggered by a timer, it will create a file every time the timer goes off. You can fix this by either using dedicated storage accounts or by using a filter on your event subscription.
Most Event Grid event handlers are easy to implement, but since you’ll probably need it, and because it doesn’t work all that well, I’m going to shortly discuss functions that are triggered by Event Grid.
When you create a new function in Visual Studio and choose the Event Grid trigger, you’ll end up with the following code.
Code Listing 38
// Default URL for triggering Event Grid function in the local environment. // http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname} using Microsoft.Azure.EventGrid.Models; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.EventGrid; using Microsoft.Extensions.Logging;
namespace FunctionApp1 { public static class Function1 { [FunctionName("Function1")] public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log) { log.LogInformation(eventGridEvent.Data.ToString()); } } } |
The default URL sort of works, but you’ll get a message that the runtime failed to bind to the EventGridEvent class. When you create the function in the portal and try to run it there, you get a NotImplementedException. However, when you try to use it directly from the topic, it works like you’d expect.
You can work around these issues by creating an HTTP trigger instead and handling the event with a web hook.
Now that we’ve seen how Event Grid handles various events and sends them to event handlers, we can create our own topic. We can send out events to our topic, which Event Grid can then send to various event handlers using a subscription.

Figure 33: Creating an Event Topic
Once your topic is created, click + Event Subscription at the top of the Overview blade. Here you can create a subscription like we did in the previous section. So, create a subscription and hook it up to a queue so we can test our custom topic.
To trigger events using our custom topic, we need to call it using an HTTP POST request. We can use Postman for this. You can find the endpoint on the Overview blade of your topic. Mine is https://succinctlyegtopic.westeurope-1.eventgrid.azure.net/api/events, which is the name of my topic, followed by the location code, followed by eventgrid.azure.net/api/events. To call the URL, append the API version to it: ?api-version=2018-01-01. You’ll also need to include a header with an access key. The access keys can be found under Access keys in the menu of your topic. For the body of your request, select raw and set the type to JSON. In the Body field enter the following JSON.
Code Listing 39
[ { "id": 1, "eventType": "mytype", "subject": "mysubject", "eventTime": "2020-02-06T16:36:00+00:00", "data":{ "Type": "OrderCreated", "Price": 100, }, "dataVersion": "1.0" } ] |
Last, set the method to POST and send the request.
If you now look in your queue, you should have a message that resembles the request, but with an added topic property. A topic can have multiple subscriptions so you can broadcast the event to multiple handlers.
You can also raise multiple events at once. The JSON payload is an array, so just adding multiple objects to the array will trigger multiple events. This is preferred over sending multiple events in separate requests.
We’re now going to create an Event Grid domain. An Event Grid domain is a collection of topics and subscriptions. It allows you to publish events to a single endpoint, after which the domain will distribute it among the various topics. Domains also allow you to manage authorization and authentication among topics. To create an Event Grid domain, go to all services and search for Event Grid. Choose the Event Grid domain and fill out the creation blade that appears. Enter a name, subscription, resource group, and location. Leave the Event Schema on the default Event Grid Schema. Click Create.

Figure 34: Creating an Event Grid Domain
In the Event Grid domain, click + Event Subscription. In the next blade, simply create a subscription, like we did before. There’s one difference though: the creation blade asks you for a Domain Topic. You can unselect Scope to domain topic, which means all events from this domain will be published to this subscription. But if you do create a new domain topic, you can publish to that topic specifically.
Let’s say your company has a sales department, a finance department, and an IT department, and they all need to subscribe to various events. So, you create a domain with three topics, a separate topic for each department. You can manage permissions per topic and create various subscriptions for each topic. However, you only need to publish events to one domain. With that in mind, create another subscription for a separate topic.

Figure 35: A Domain with Multiple Topics
Publishing events to the domain works the same as publishing events to a topic, with one minor difference: you have to specify the topic in the JSON payload.
Code Listing 40
[ { "id": 1, "eventType": "mytype", "subject": "mysubject", "eventTime": "2020-02-06T16:36:00+00:00", "data":{ "Type": "OrderCreated", "Price": 100, }, "dataVersion": "1.0" } ] |
This event is now handled by all subscriptions in the salestopic, and by the domain-scope event subscriptions.
To make handling various events more manageable, consider using the Event Type filter. This is like subject filtering, which we’ve seen in the storage account example, but a little less fine grained. Like the subject, the event type is part of the JSON you post to your endpoint, so it’s up to you which types you give to your events. Using the type filter when creating a subscription prevents certain types of events from being published to the event handler. That also means that you can introduce new event types without them being handled by the subscription. This saves you from having to create a topic for each separate event concerning sales orders, or whatever business object you have.
Azure Event Grid allows you to create event-based applications. It allows you to react to events from Azure itself, like blobs or resources being created, but you can also add your own events using topics. With subscriptions, you can route events to specific handlers. Each topic can have multiple subscriptions, so each event can be handled by multiple handlers. By using an event domain, you can manage your custom topics and subscriptions more easily, and manage authorization and authentication in a single place. Using custom events with webhook handlers allows you to handle any event how you want to.