In our Drone Pizza Delivery application we have built 2 Microservices – CommandCenter and ProcessCenter. You may have notice there are some classes that are used in both these Microservices which makes the code redundant. We can take these common classes and codes to a new Class Library project and create a NuGet package of it.
Then we can use this NuGet Package in both these Microservices. This will remove the problem of code redundancy from our app.
You can find this tutorial’s the complete Source Code at my GitHub Repository.
Page Contents
In Visual Studio create a new Class Library (.NET Core) project and name it Common.
Then select properties and make sure you have selected .NET 8.0 as the target framework.
Next add the following NuGet package to the solution:
MassTransit.RabbitMQ
MongoDB.Driver
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Binder
Microsoft.Extensions.DependencyInjection
These are the same packages we are using in both the Microservices.
In this project we will move common files and codes from both the microservices. So open CommandCenter microservice project and move the following folders to the “Common” project.
Note that the files in the above 3 folders are also used in the ProcessCenter microservices. So, by moving these files to a comman project we will be removing redundant files from both the microservices.
Next, move the Contracts.cs file from the Infrastructure folder to the Common project. I have shown this in the below image:
Now we will create an extension method of MassTransit code used in both Microservices. So in the “Common” project create a new folder called MassTransit and inside it create a new class called Extensions.cs whose code is given below:
using CommandCenter.Setting;
using MassTransit;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
namespace Common.MassTransit
{
public static class Extensions
{
public static IServiceCollection AddMassTransitWithRabbitMQ(this IServiceCollection services)
{
services.AddMassTransit(x =>
{
x.AddConsumers(Assembly.GetEntryAssembly());
x.UsingRabbitMq((context, configurator) =>
{
var configuration = context.GetService<IConfiguration>();
var serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
var rabbitMqSettings = configuration.GetSection(nameof(RabbitMQSettings)).Get<RabbitMQSettings>();
configurator.Host(rabbitMqSettings.Host);
configurator.ConfigureEndpoints(context, new KebabCaseEndpointNameFormatter(serviceSettings.ServiceName, false));
configurator.UseMessageRetry(b =>
{
b.Interval(3, TimeSpan.FromSeconds(5));
});
});
});
return services;
}
}
}
Now it’s turn to create a NuGet Package for the “Common” project. So open Package Manager Console and add the following command:
dotnet pack --output commonpackage
This command will create the package inside commonpackage folder of your project.
If you open this folder then you will NuGet package file called Common.1.0.0.nupkg there. Common is the name of the package, 1.0.0 is the version and NuGet packages have .nupkg file extension.
Next run the following command to add a NuGet source:
dotnet nuget add source D:\commonpackage -n MyCommon
Here I have named NuGet source as MyCommon and my NuGet Package is kept inside D:\commonpackage. Note that the name of the Package will be the same as the name of the project, in our case the name of the project was Common so the NuGet package will also be named as common.
Before proceeding, copy the package file we created to D:\commonpackage location of your pc.
.Now we will use this NuGet package in both of our Microservices. So kindly close and reopen the CommandCenter and ProcessCenter microservice applications on Visual Studio, this is necessary so that we can add our new package to the solution file.
Now on the Visual Studio, open NuGet Package Manager ➤ Manage NuGet Packages for Solutions. On the package source drop down, you will see MyCommon, so select it. Then click the Browse link and you will see the “Common” package is visible there, so install it on the CommandCenter and ProcessCenter microservices.
Now all you have to do is remove the common files and use it from this NuGet package in both the Microservices.
Also change the Program.cs class to use AddMassTransitWithRabbitMQ() from the NuGet Package in both the Microservices. To do this, open Program.cs class of CommandCenter microservice and remove the below code:
builder.Services.AddMassTransit(x =>
{
x.AddConsumers(Assembly.GetEntryAssembly());
x.UsingRabbitMq((context, configurator) =>
{
var rabbitMqSettings = builder.Configuration.GetSection(nameof(RabbitMQSettings)).Get<RabbitMQSettings>();
configurator.Host(rabbitMqSettings.Host);
configurator.ConfigureEndpoints(context, new KebabCaseEndpointNameFormatter(serviceSettings.ServiceName, false));
});
});
Add AddMassTransitWithRabbitMQ() method:
builder.Services.AddMongo().AddMongoRepository<Order>("pizzaItems").AddMassTransitWithRabbitMQ();
The updated Program class should look as shown below:
using CommandCenter.Entity;
using CommandCenter.MongoDB;
using CommandCenter.Setting;
using Common.MassTransit;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var serviceSettings = builder.Configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
builder.Services.AddMongo().AddMongoRepository<Order>("pizzaItems").AddMassTransitWithRabbitMQ();
builder.Services.AddControllers(options =>
{
options.SuppressAsyncSuffixInActionNames = false;
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
In the Program.cs class of ProcessCenter microservice. Remove the following code lines.
builder.Services.AddMassTransit(x =>
{
x.AddConsumers(Assembly.GetEntryAssembly());
x.UsingRabbitMq((context, configurator) =>
{
var configuration = context.GetService<IConfiguration>();
var serviceSettings = configuration.GetSection(nameof(ServiceSettings)).Get<ServiceSettings>();
var rabbitMqSettings = configuration.GetSection(nameof(RabbitMQSettings)).Get<RabbitMQSettings>();
configurator.Host(rabbitMqSettings.Host);
configurator.ConfigureEndpoints(context, new KebabCaseEndpointNameFormatter(serviceSettings.ServiceName, false));
configurator.UseMessageRetry(b =>
{
b.Interval(3, TimeSpan.FromSeconds(5));
});
});
});
Add AddMassTransitWithRabbitMQ() method:
builder.Services.AddMongo().AddMongoRepository<Process>("processItems").AddMongoRepository<Order>("pizzaItems").AddMassTransitWithRabbitMQ();
The updated code of the Program class is:
using Polly.Timeout;
using Polly;
using ProcessCenter.Client;
using ProcessCenter.Entity;
using CommandCenter.MongoDB;
using CommandCenter.Entity;
using Common.MassTransit;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddMongo().AddMongoRepository<Process>("processItems").AddMongoRepository<Order>("pizzaItems").AddMassTransitWithRabbitMQ();
builder.Services.AddHttpClient<OrderClient>(a =>
{
a.BaseAddress = new Uri("https://localhost:44393");
})
.AddTransientHttpErrorPolicy(b => b.Or<TimeoutRejectedException>().WaitAndRetryAsync(
5,
c => TimeSpan.FromSeconds(Math.Pow(2, c))
))
.AddTransientHttpErrorPolicy(b => b.Or<TimeoutRejectedException>().CircuitBreakerAsync(
3,
TimeSpan.FromSeconds(15)
))
.AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(1));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Finally, on the ProcessCenter project do the following 3 things:
In the below image I have shown how the final files and folder structure looks for both the microservices. We have removed as much as 60% of redundant code now.
In this tutorial we covered code refactoring in microservices. We first moved the comman files and folder to a new class project and created a NuGet package of it. Then used that package in both the microservices.
SHARE THIS ARTICLE