Implementing Event-Driven in .Net Core 5

Implementing Event-Driven in .Net Core 5

The event-driven is an architecture that uses events to communicate changes of states to applications that are interested in different events.

This type of architecture decouples services by using Service buses. This allows the services involved to be scaled, updated, and deployed independently.

This post will explain how to implement an event-driven architecture with MassTransit (a library to configure and send events messages to a Message broker) and RabbitMQ (a message broker that handles events messages).

The solution is composed of 4 parts.

  • The Dating API: This is a Web API application that receives all the petitions from the Angular app.
  • Angular APP: This is the client application where the user interacts.
  • Logger Microservice: This is a simple application that will be used to log messages sent by the Dating App.
  • RabbitMQ: This is the message broker that will be used for the Dating API and the Logger Microservice to interchange messages.

A simple scenario:

To understand how it works we'll go through the next scenario.

1.- The user registers in the Angular app

2.- The Dating API receives the petition and registers the User in their database.

3.- The Dating API sends a RegisteredCommand using MassTransit to RabbitMQ queue.

4.- The Logger Microservice that is a Consumer/Subscribed Service to the RegisteredCommand will get the message using MassTransit and will log the message. (For this example will log only on the terminal)

No alt text provided for this image

Section of this article.

This post is divided into 4 sections:

  • Section 1 will describe the LogerMicroservice and the Dating App and how the Dating App implements internally the CQRS pattern using MediatR.
  • Section 2 will describe MassTransit in more detail. It will explain what is it and how to implement distributed systems using MassTransit and RabbitMQ.
  • Section 3 will briefly explain what RabbitMQ is and how to run RabbitMQ using docker.
  • Section 4 will go through the simple scenario explained above and test that the applications interact through event messages.

Section 1.- What is the LogerMicorservice and what is the Dating APP and how does it implement to implements CQRS.

What is Logger Microservice?

The Logger Microservice is just a small application inside the solution that is subscribed to the RegisterUserCreatedCommand event. It is the Consumer and it will be listening for the new-user-registered event.

It is in charge of logging in to the console each time a new user gets registered.

What is the Dating APP?

The Dating APP is a Web API application that sends the RegisterUserCreatedCommand event to the RabbitMQ queue using the MassTransit framework (Explained below).

This project implements the CQRS pattern using the MediatR library.

Note: It is important to not mix the MassTransit commands used by MassTransit to communicate the events externally with the commands used by MediatR for the internal communication inside the DatingApp. For this example, there is only one command used by MassTransit (RegisterUserCreatedCommand) all others will be used by MediatR.

CQRS (Commands and Queries Responsibility Segregation) is a pattern that tells you to divide your read-only requests (Queries)and your writing request (Commands) and to put all the logic in Handlers.

The main idea is to go to different databases specialized and optimized each one for a different purpose. One for reading and one for updating.

No alt text provided for this image

Although this is the main advantage when implementing CQRS, by implementing it using the MediatR library we get more internal advantages.

For example, the logic of the application is moved into Handlers. This makes it easier to maintain and easier to create unit tests.

No alt text provided for this image

The commands are sent from the controller to the handlers and they need to implement from IRequest<T> and they contain transport the information needed in the Handlers.

No alt text provided for this image

Controllers become orchestrators and all the logic is moved into the handlers.

No alt text provided for this image

IPipelineBahaviours

Validations and caching can be placed in one place by implementing IPipelineBahaviour. The pipelines behaviors act as a middleware for the commands and queries, which means that all commands and queries will go through these Pipelines which makes it possible to have a centralized validator and caching.

The Validation logic.

No alt text provided for this image

The validators

To validate a command or a query they need to implements the library fluent validator. Fluent Validator is a library that helps to write more readable validators and to write validations easily.

In our scenario, each time a RegisterUserCommand is sent through the mediator, the information contained in the command will be validated by the rules inside RegisterUserCommandValidator.

Now all validations will exist only in one place and with the fluent validator library, it is Teasy to write complex validations.

No alt text provided for this image

The cache pipeline behavior

In the same way, requests go through the pipeline to get validated, it is possible to implement a cache for the incoming query requests.

Look in the next image how easy is to create a new Behaviour and implement an IMemoryCache in the incoming queries requests.

No alt text provided for this image

Section 2.- How to implement distributed systems using MassTransit and RabbitMQ

What is MassTransit?

MassTransit is a free, open-source distributed application framework for DotNET. MassTransit makes it easy to create applications and services that leverage message-based, loosely-coupled asynchronous communication for higher availability, reliability, and scalability.

5 parts are needed in order to implement a driven event architecture

No alt text provided for this image

Implementing TransMassive in the Producer (DatingAPP)

1.- Install the NuGet package MassTransit.RabbitMQ, MassTransit.Extensions.DependencyInjection, MassTransit.AspNetCore.

No alt text provided for this image

2.- Add a new configuration section in the appsettings.json

No alt text provided for this image

3.- Add a new configuration class to serialize the RabbitMqSettings in the appsettings.json.

No alt text provided for this image




4.- Add the MassTransit to the service collection the RabbitMQ configuration.

No alt text provided for this image

5.- Create the Command that will be shared between the Producer and the Consumer. Create the command in a common library project so they can share the same object.

No alt text provided for this image

6.- Add the reference to the Common library project to be able to reference the RegisterUserCreatedCommand.

No alt text provided for this image

7.- Use MassTransit to send the command to the RabbitMQ queue.

  1. Inject the IPublishEndpoint that is an interface from MassTransit that will be in charge to publish the command to the RabbitMQ.
  2. Instantiate the RegisterUserCreatedCommand with the AppUserId that will be transferred in the event message.
  3. Publish the event message.

No alt text provided for this image


Implementing TransMassive in the Consumer (Logger Microservice)

1.- Install the Nuget package MassTransit.RabbitMQ

No alt text provided for this image

2.- Add a reference to the common library project so the project can reference the RegisterUserCreatedCommand.

No alt text provided for this image

3..- Create the BusControl with the next configuration

No alt text provided for this image

  1. Create the variable bus calling the bus factory for RabbitMQ.
  2. Add the configuration to communicate with the RabbitMQ server. Change the parameters in case you changed the configuration in your RabbitMQ server. By default it has the amqp protocol, the user and password is "guest", and the port to communicate is the 5676.
  3. Specify the name of the queue where the application will be listening for new events.
  4. Specify the command that the application will be expecting to process.


Section 3. RabbitMQ

RabbitMQ is a messaging broker - an intermediary for messaging. It gives your applications a common platform to send and receive messages, and your messages a safe place to live until received.

No alt text provided for this image

For testing purposes, the RabbitMQ server will be installed using docker by running the next command:

 docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management        

Check that RabbitMQ is running by going to the management web page. (http://localhost:15672)

No alt text provided for this image

Section 4: Testing.

To test the application it is needed to run the applications.

Go to the registration page on http://localhost:4200

No alt text provided for this image

Check that the response was successful (code 201) in the DatingAPP console:

No alt text provided for this image

Check that the logger-microservice received the event message with the new user Id

No alt text provided for this image

In the RabbitMQ management application, it is possible to see that the queue was created

No alt text provided for this image


The code can be found in this Github link


UPDATE JAN 28 2022

The update is about how to run microservices locally easily using dotnet Tye.

Tye is a developer tool that makes developing, testing, and deploying microservices and distributed applications easier. Project Tye includes a local orchestrator to make developing microservices easier and the ability to deploy microservices to Kubernetes with minimal configuration.


Tye allows running all our services with just one command.

First, need to install Tye. The available version for me is 0.10.0-alpha.21420.1

dotnet tool install --global Microsoft.Tye --version 0.10.0-alpha.21420.1        

Second, need to create a Tye File

tye init        

By default, tye will find all .net core projects and add them to the tye.yaml file.

Third, add the missing services from Docker (RabbitMq and Angular app).

No alt text provided for this image

Finally, run tye.

run tye        

How to add the Angular Application into the Docker Hub.

No need to follow the next steps because my application is already in my Docker Hub and anyone has access to the Docker container.

As I said before the Rabbit MQ service and the angular app should exist in the Docker Registry.

In my case, I had to add my angular application to my Docker Hub by adding the docker file inside the application folder.

No alt text provided for this image

Generate the docker image

command example: 
docker build -t dockerhub_name/image_name:tag dockerfile_location

docker build -t mavidocker/angular-app:latest .         

I uploaded the docker image to my docker Hub

docker login

docker push mavidocker/angular-app:latest         


To view or add a comment, sign in

More articles by David Mata Viejo

Others also viewed

Explore content categories