Creating a Newsletter Manager with Hangfire

Creating a Bulk-Email Management System IV – APIs

Finally, we’ve come to the heart of the infrastructure project which is the API endpoints. This will be developed as a set of Azure Functions. It’s dirt cheap to host these serverless functions in Azure and I’ve written extensively about it. It’s been a minute I developed and deployed core API projects outside of Azure given the benefits of low maintenance among others that come with Azure Serverless Functions. As a recap, this whole project is available in my GitHub repo.

There’s not much to this project and much of it is repetitive. In other words, the endpoints for Subscribers are similar to those for Newsletters and Requests. I simply focus on the Requests as it’s the main one for implementing the core functionality of the project.

3. BabaFunkeEmailManager.Functions Project

Step I – Right-click the blank solution to add a New Project; select Azure Functions from the list of templates and name it. Mine’s BabaFunkeEmailManager.Functions. 

Step 2 – Add the project references BabaFunkeEmailManager.Data and BabaFunkeEmailManager.Service.

Step 3 – Set up the Dependency Injection Container

In terms of Setup, we need to register the services and repositories defined in the BabaFunkeEmailManager.Service project to the DI container. For this, I created an extension method to keep the Startup.cs file clean

The Startup.cs file in itself needs to be set up for the Azure Storage services – Queue and Table Storage – and the email sender, in this case SendGrid and FluentEmail.

Step 4 – Create the Endpoints

Here, we simply create a series of Azure Functions, one per endpoint. Each one relies on the Service to implement its task as we’d already done those in the service project housing the business logics. Using the RequestHeader as example, we have the following set of HttpTrigger functions.

AddRequestHeader.cs is where the request to send a bulk email gets created. First, it adds the requestheader as a record to Table Storage. If successful, it calls a private method that iterates over the list of filtered subscribers defined by the SubscriberSubCategory value of the RequestHeader, creating an instance of a RequestDetail for each and adding it to the Message Queue via the QueueService created in the Services project.

For every added request, there is a private method that’s called which loops through the list. Note that you may want to consider using a Linq here to skip and take because you can’t have more than 1,000 items in a queue at once. I experienced this when I had a request sent with over 3k members in the list, hence the modified code.

Step 5 – Add a QueueTrigger

Finally, we create an Azure Queue Trigger that gets called every time a message is added to the Queue. It simply deserializes each message back into a RequestDetail, calls the EmailService to send an email and adds its returned response to another table called EmailReports. For this last part, I simply use an OutputBinder which is an out-of-the-box attribute provided by Azure Functions for adding items to an Azure Table. It’s an alternative to the approach I took with the other entities and suitable for this use case where we are only adding items to a table and nothing more.

Conclusion

That’s it for the APIs. You could actually go with this especially if your email AddRequest endpoint isn’t going to be running any lengthy process that would exceed the standard timeouts for http calls. If, on the other hand, you plan on sending tons of messages, then you should consider a WebJob in place of the Queue Trigger. In Part V, I walk through a WebJob creation, testing and deployment.