Part 3: Implementing the Billing Service with Event Driven Domain using .Net 8

Fábio Salomão
3 min readJun 5, 2024

--

In the previous part, we implemented the order service, which publishes events to RabbitMQ. Now, let’s create the billing service, which will consume these events and generate corresponding invoices.

Creating the .Net 8 Project for the Billing Service

  1. Creating the Project: Open Visual Studio 2022 and create a new ASP.NET Core Web API project.
  2. Configuring the Project: Name the project BillingService and select .Net 8 as the framework version.
  3. Adding Dependencies: Add the following dependencies to your project:
dotnet add package RabbitMQ.Client
dotnet add package Microsoft.Extensions.Hosting

Implementing the Billing Service

Invoice Model

Create a new folder called Models and add the following Invoice class:

namespace BillingService.Models
{
public class Invoice
{
public Guid Id { get; set; }
public Guid OrderId { get; set; }
public required string ProductName { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Total => Quantity * Price;
public DateTime CreatedAt { get; set; }
}
}

Event Subscriber

Let’s create a service to consume events. Create a folder called Services and add the following interface and class:

namespace BillingService.Services
{
public interface IEventSubscriber
{
void Subscribe();
}
}
using System.Text;
using System.Text.Json;
using BillingService.Models;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace BillingService.Services;

public class RabbitMqEventSubscriber(IConnection connection) : IEventSubscriber
{
public void Subscribe()
{
using var channel = connection.CreateModel();
channel.QueueDeclare(queue: "orders", durable: false, exclusive: false, autoDelete: false, arguments: null);

var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
var order = JsonSerializer.Deserialize<Order>(message);

if (order == null) return;
var invoice = new Invoice
{
Id = Guid.NewGuid(),
OrderId = order.Id,
ProductName = order.ProductName,
Quantity = order.Quantity,
Price = order.Price,
CreatedAt = DateTime.UtcNow
};

Console.WriteLine($"Invoice generated: {JsonSerializer.Serialize(invoice)}");
};

channel.BasicConsume(queue: "orders", autoAck: true, consumer: consumer);

Console.WriteLine("Press [enter] to exit.");
Console.ReadLine();
}
}

To deserialize the order events, add an Order class similar to the one used in the order service:

namespace BillingService.Models
{
public class Order
{
public Guid Id { get; set; }
public required string ProductName { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public DateTime CreatedAt { get; set; }
}
}

Configuring RabbitMQ in Startup

In the Program.cs file, configure the RabbitMQ connection and register the IEventSubscriber:

using BillingService.Services;
using RabbitMQ.Client;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<IConnection>(sp =>
{
var factory = new ConnectionFactory() { HostName = "localhost" };
return factory.CreateConnection();
});

builder.Services.AddSingleton<IEventSubscriber, RabbitMqEventSubscriber>();

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

var subscriber = app.Services.GetRequiredService<IEventSubscriber>();
subscriber.Subscribe();

app.Run();

Testing the Billing Service

First, let’s configure Visual Studio 2022 to initialize the 2 projects when running the application with F5.
Right-click on the project solution in Solution Explorex and select the “Multiple start projects” option and in the “actions” select “start” for both projects as shown in the image:

Verify the Output: Observe the console of the billing service. When an order is created by the order service, the billing service should consume the event and generate an invoice, displaying the details in the console.

In the next article, we will implement the invoice persistence service in a database using Entity Framework Core.

See you then!

--

--

Fábio Salomão

Developer since 2009 with experience in Microsoft .Net and Full Stack skills. React specialist, focused on creating innovative and efficient solutions.