Creating a Newsletter Manager with Hangfire

Creating a Bulk-Email Management System III – Services

The Service project is a class library project that holds the business logics for CRUD operations relative to the services and repositories as well as mappers. It’s split into 3 distinct folder structures namely, Repositories, Services and Mappers. More details below

2. BabaFunkeEmailManager.Service Project

Step I – Right-click the blank solution to add a New Project. Select the ‘Class Library’ project option; make sure it’s C# and targets .Net Standard or .Net Core. I name mine BabaFunkeEmailManager.Service. 

Step 2 – Add the Project References and Nuget Packages

Add a reference to the BabaFunkeEmailManager.Data project since we’ll be referencing the models in the services. Add the following Nuget Packages

Step 3 – Create the Services

We implement all the CRUD related functionalities for the system stopping short of directly interacting with the data layer. Instead, the services call the repositories for any interactions with the data store.

For my interfaces, I create a generic one for basic CRUD operations. In other words, services such as Request, Newsletter and Subscriber all implement methods for creating new entities, requesting existing entities by id or all, updating existing entities and deleting entities from the database. To avoid unnecessary code duplication (think the DRY principle), we simply morph all into one interface that will be implemented by all 3 – IService.

ISubscriberService.cs inherits the generic IService interface to provide a functionality for getting a filtered subscribers list. This is required for sending emails to selected subcategories in our list.

For the corresponding implementation of the interfaces above, I touch on two examples for brevity. The complete implementation can be found in the GitHub project.

The QueueService’s sole responsibility is to add a RequestDetail object to the MessageQueue where it’ll be picked up and deserialized for sending via the EmailService. Any addition to this queue, triggers a call to the Queue Trigger Azure Function or Webjob which will be created later.

The EmailService uses the FluentEmailFactory exposed by the FluentEmail Nuget package to end out emails. My private BuildEmail method creates a structure for the email by adding a header, footer and body. Some of the elements of the email structure e.g. body (actual content of the email), name of recipient will be provided in each request detail object. FluentEmail does support templates so you could explore the option as an alternative to my hardcoded structure in the private method.

Step 4 – Create the Repositories

We create the interfaces and implementation that directly communicate with our Data Store, Azure Table Storage. The 3 main tables are Subscriber, Newsletter and RequestHeader so we define their corresponding repos as below.

First the interfaces,

And the implementations. For brevity, I share only the SubscriberRepository here.

Step 5 – Create the Mappers

Finally, we have the mappers which act as the bridge between the models and entities. I prefer a custom mapper to AutoMapper since this is a simple scenario. Recall that the entities directly communicate with the Data Store while the models are client-facing.

First a generic interface,

And the implementation for corresponding model/entity relationship.

Conclusion

That’s it for the Services. The logical split of the system into projects ensures we have a proper organization and makes it easy to re-use shared resources as we’ll see. In Part IV, I focus on the APIs. Note that the project is available on Github for ease of replicating.