This post was originally published here
In my previous post I showed how we can use the recently announced Event Grid service to integrate Azure services with each other. In this post, I will show how we can send custom events from any application or service into Event Grid, allowing us to integrate any service. My next post will show you in detail how we can subscribe to these custom events.
We will start by creating a new Event Grid Topic in the portal. Go to the Event Grid Topics blade, add a new Topic, and provide the details.
We will now create an application, which will send custom events into our topic. By setting the subject and event type, we can later on subscribe to specific events. I used an application I have built for a shipping company as inspiration, which they use for their day to day work. In this sample, we build a console app, which will generate events when an order has been placed, as well as when a repair has been requested.
Data Classes
Once created, we will first add the classes which will represent the data of the orders and repairs. Both of these inherit from the ShipEvent class, which holds the common data.
/// <summary> /// Event sent for a specific ship. /// </summary> public class ShipEvent { /// <summary> /// Name of the ship. /// </summary> public string Ship { get; set; } /// <summary> /// Type of event. /// </summary> public string Type { get; set; } } |
/// <summary> /// Used to place an order. /// </summary> public class Order : ShipEvent { /// <summary> /// Name of the product. /// </summary> public string Product { get; set; } /// <summary> /// Number of items to be ordered. /// </summary> public int Amount { get; set; } /// <summary> /// Constructor. /// </summary> public Order() { Type = "Order"; } } |
/// <summary> /// Used to request a repair. /// </summary> public class Repair : ShipEvent { /// <summary> /// Device which needs to be repaired. /// </summary> public string Device { get; set; } /// <summary> /// Description of the defect. /// </summary> public string Description { get; set; } /// <summary> /// Constructor. /// </summary> public Repair() { Type = "Repair"; } } |
Custom Event Class
Now we will create our custom Event class, which follows the structure of the Event Grid events schema. In this sample, we will only send out shipevent types of events, but you could easily expand this with other event types as well. We use the UpdateProperties property to update the Subject, which will later on be used to filter our messages in our subscriptions. Here we also include our Data, which is our payload of the Order or Repair we are sending.
/// <summary> /// Event to be sent to Event Grid Topic. /// </summary> public class Event { /// <summary> /// This will be used to update the Subject and Data properties. /// </summary> public ShipEvent UpdateProperties { set { Subject = $"{value.Ship}/{value.Type}"; Data = value; } } /// <summary> /// Gets the unique identifier for the event. /// </summary> public string Id { get; } /// <summary> /// Gets the publisher defined path to the event subject. /// </summary> public string Subject { get; set; } /// <summary> /// Gets the registered event type for this event source. /// </summary> public string EventType { get; } /// <summary> /// Gets the time the event is generated based on the provider's UTC time. /// </summary> public string EventTime { get; } /// <summary> /// Gets or sets the event data specific to the resource provider. /// </summary> public ShipEvent Data { get; set; } /// <summary> /// Constructor. /// </summary> public Event() { Id = Guid.NewGuid().ToString(); EventType = "shipevent"; EventTime = DateTime.UtcNow.ToString("o"); } } |
Settings
In the Program class, add two properties. The first will hold the endpoint of the Event Grid Topic we just created, while the second will hold the key used to connect to the topic.
/// <summary> /// Send events to an Event Grid Topic. /// </summary> public class Program { /// <summary> /// Endpoint of the Event Grid Topic. /// Update this with your own endpoint from the Azure Portal. /// </summary> private const string TOPIC_ENDPOINT = "https://eventgridcustomeventstopic.westcentralus-1.eventgrid.azure.net/api/events"; /// <summary> /// Key of the Event Grid Topic. /// Update this with your own key from the Azure Portal. /// </summary> private const string KEY = "1yroJHgswWDsc3ekc94UoO/nCdClNOwEuqV/HuzaaDM="; } |
Send To Event Grid
Next we will add the method to this class, which will be used to send our custom events to the Topic. At this moment, we don’t have a SDK available yet, but luckily Event Grid does expose a powerful API which we can leverage using a HttpClient. When using this API, we will need to send in a aeg-sas-key with the key we retrieved from the portal.
/// <summary> /// Send events to Event Grid Topic. /// </summary> private static async Task SendEventsToTopic(object events) { // Create a HTTP client which we will use to post to the Event Grid Topic var httpClient = new HttpClient(); // Add key in the request headers httpClient.DefaultRequestHeaders.Add("aeg-sas-key", KEY); // Event grid expects event data as JSON var json = JsonConvert.SerializeObject(events); // Create request which will be sent to the topic var content = new StringContent(json, Encoding.UTF8, "application/json"); // Send request Console.WriteLine("Sending event to Event Grid..."); var result = await httpClient.PostAsync(TOPIC_ENDPOINT, content); // Show result Console.WriteLine($"Event sent with result: {result.ReasonPhrase}"); Console.WriteLine(); } |
Main Method
And finally we will implement the main method. In this method, the user specifies what they want to do, and provides the data for that action. We will then send this data to our Topic.
/// <summary> /// Main method. /// </summary> public static void Main(string[] args) { // Set default values var entry = string.Empty; // Loop until user exits while (entry != "e" && entry != "exit") { // Get entry from user Console.WriteLine("Do you want to send an (o)rder, request a (r)epair or (e)xit the application?"); entry = Console.ReadLine()?.ToLowerInvariant(); // Get name of the ship Console.WriteLine("What is the name of the ship?"); var shipName = Console.ReadLine(); // Order var events = new List<Event>(); switch (entry) { case "e": case "exit": continue; case "o": case "order": // Get user input Console.WriteLine("What would you like to order?"); var product = Console.ReadLine(); Console.WriteLine("How many would you like to order?"); var amount = Convert.ToInt32(Console.ReadLine()); // Create order event // Event Grid expects a list of events, even when only one event is sent events.Add(new Event { UpdateProperties = new Order { Ship = shipName, Product = product, Amount = amount } }); break; case "r": case "repair": // Get user input Console.WriteLine("Which device would you like to get repaired?"); var device = Console.ReadLine(); Console.WriteLine("Please provide a description of the issue."); var description = Console.ReadLine(); // Create repair event // Event Grid expects a list of events, even when only one event is sent events.Add(new Event { UpdateProperties = new Repair { Ship = shipName, Device = device, Description = description } }); break; default: Console.Error.WriteLine("Invalid entry received."); continue; } // Send to Event Grid Topic SendEventsToTopic(events).Wait(); } } |
Testing
Now when we run our application, we can start sending in events to Event Grid, after which we can use subscriptions to pick them up. More on these subscriptions can be found in my previous post and next post. The complete code with this blog post can be found here.