Local Development with Azure Functions and Event Grid

For the past couple of days I have been working with Azure Functions and Event Grid. 

The challenge I encountered was getting it so I could run and debug my Azure Functions locally, specifically the Even Grid Azure Function.

Finally figured it out!

For my example I am using two Azure Functions, the first is a Http Trigger function and the second is an Event Grid Trigger function.

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.EventGrid;
using Microsoft.Azure.EventGrid.Models;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Teamaloo.FunctionApp.Users.Data;
using Teamaloo.FunctionApp.Users.Helpers;
using Teamaloo.FunctionApp.Users.Models;

namespace Teamaloo.FunctionApp.Users
{
    public static class UserAddHttpTrigger
    {
        [FunctionName("AddAsync")]
        public static async Task<IActionResult> AddAsync(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = "users")] HttpRequest req,
            ILogger log)
        {
            var userAdd =
                 JsonConvert.DeserializeObject<UserAdd>(
                     await new StreamReader(req.Body).ReadToEndAsync());

            if (userAdd == null)
            {
                userAdd = new UserAdd();
            }

            if (!userAdd.IsValid)
            {
                return new BadRequestObjectResult(userAdd.ValidationResults);
            }

            var secretService =
                new AzureKeyVaultSecretService();

            var userDataRepository =
                new UserDataRepository(secretService);

            var userData =
                new UserData
                {
                    Name = userAdd.Name,
                    Email = userAdd.Email
                };

            userData =
               await userDataRepository.AddAsync(userData);

            var userAdded =
                new UserAdded
                {
                    Id = userData.Id,
                    Name = userData.Name,
                    Email = userData.Email
                };

            var topicEndpoint =
                await secretService.GetSecretAsync("AzureEventGridTopicEndpoint");

            var topicAccessKey = 
                await secretService.GetSecretAsync("AzureEventGridTopicAccessKey");

            var events = new List<EventGridEvent>();
            var eventGridEvent = new EventGridEvent();

            eventGridEvent.Id = Guid.NewGuid().ToString();
            eventGridEvent.Subject = $"users/{userAdded.Id}";
            eventGridEvent.EventType = "UserAdded";
            eventGridEvent.EventTime = DateTime.UtcNow;
            eventGridEvent.Data = userAdded;
            events.Add(eventGridEvent);

            var content = JsonConvert.SerializeObject(events);

            var client = new HttpClient();

            client.DefaultRequestHeaders.Add("aeg-sas-key", topicAccessKey);

            var httpContent = new StringContent(content, Encoding.UTF8, "application/json");

            await client.PostAsync(topicEndpoint, httpContent);

            return new OkObjectResult(userAdded);
        }
    }
}

This function simply adds a User to a SQL Server database.

The class AzureKeyVaultSecretService, is just a help class that extracts Environment Variables from local.settings.json, when running locally, and Azure Key Vault, when running in production.

// Default URL for triggering event grid function in the local environment.
// http://localhost:7071/runtime/webhooks/EventGrid?functionName={functionname}

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Azure.EventGrid.Models;
using Microsoft.Azure.WebJobs.Extensions.EventGrid;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Teamaloo.FunctionApp.Users
{
    public static class UserAddedEventGridTrigger
    {
        [FunctionName("UserAddedEventGridTrigger")]
        public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
        {
            log.LogInformation(JsonConvert.SerializeObject(eventGridEvent,Formatting.Indented));
        }
    }
}

Download the Azure Grid Emulator at https://github.com/ravinsp/eventgrid-emulator. and then configure the emulator-config.json file for the Azure Grid Emulator.

{
  "port": 5000,
  "topics": [{
    "name": "Users",
    "subscriptions": [{
      "name": "UserAddedEventGridTrigger",
      "eventTypes": ["UserAdded"],
      "SubjectBeginsWith": "",
      "SubjectEndsWith": "",
      "endpointUrl": "http://localhost:7071/runtime/webhooks/eventgrid?functionName=UserAddedEventGridTrigger",
      "dispatchStrategy": "DefaultHttpStrategy"
    }]
  }],
  "dispatchStrategies": [{
    "name": "DefaultHttpStrategy",
    "type": "EventGridEmulator.Logic.DispatchStrategies.DefaultHttpStrategy"
  }]
}

Set local.settings.json configuration.

Run your Azure Function project and the Event Grid Emulator. From Postman I make a POST call to http://localhost:7071/api/users.

Output from Azure Grid Emulator looks good! That’s it!

Related Articles

Leave a Reply

Your email address will not be published.