Introduction
Microservices architecture allows developers to build scalable, flexible, and independently deployable services. In the .NET ecosystem, creating microservices has become more accessible with modern tools like ASP.NET Core, Docker, and Kubernetes.
This article provides a step-by-step guide to building microservices in .NET, covering project setup, communication between services, and deployment practices.
🧱 What Are Microservices?
Microservices are small, autonomous services that work together. Each service is:
-
Focused on a single business capability.
-
Independently deployable.
-
Capable of running its own data and logic.
-
Communicating over lightweight protocols like HTTP or messaging queues.
🛠️ Step 1. Create the Solution and Projects
Use the CLI or Visual Studio to create a solution with multiple projects.
dotnet new sln -n MicroservicesDemo
cd MicroservicesDemo
# Create services
dotnet new webapi -n ProductService
dotnet new webapi -n OrderService
# Add to solution
dotnet sln add ProductService/ProductService.csproj
dotnet sln add OrderService/OrderService.csproj
🗃️ Step 2. Define the Project Structure
Typical structure for each microservice:
ProductService/
│
├── Controllers/
├── Models/
├── Data/
├── Services/
├── Program.cs
└── appsettings.json
Repeat the structure for OrderService.
📦 Step 3. Implement a Microservice (Example: ProductService)
Model: Product.cs
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
DbContext: ProductContext.cs
public class ProductContext : DbContext
{
public ProductContext(DbContextOptions<ProductContext> options) : base(options) { }
public DbSet<Product> Products { get; set; }
}
Controller: ProductsController.cs
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly ProductContext _context;
public ProductsController(ProductContext context) => _context = context;
[HttpGet]
public async Task<IEnumerable<Product>> Get() => await _context.Products.ToListAsync();
}
Register in Program.cs
builder.Services.AddDbContext<ProductContext>(opt =>
opt.UseInMemoryDatabase("ProductDb"));
builder.Services.AddControllers();
🔗 Step 4. Communicate Between Microservices
There are several communication patterns:
1. HTTP REST (Simple)
Use HttpClient or Refit to call APIs between services.
public class ProductClient
{
private readonly HttpClient _httpClient;
public ProductClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<List<Product>> GetAllProductsAsync()
{
var response = await _httpClient.GetFromJsonAsync<List<Product>>("http://productservice/api/products");
return response ?? new List<Product>();
}
}
Register
builder.Services.AddHttpClient<ProductClient>();
2. gRPC (Efficient binary protocol)
dotnet new grpc -n ProductGrpcService
3. Message Queue (Event-driven)
Use RabbitMQ, Azure Service Bus, or Kafka for async communication.
// Publish product created event
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.QueueDeclare(queue: "product-created");
var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { Id = 1, Name = "Item" }));
channel.BasicPublish(exchange: "", routingKey: "product-created", body: body);
🧪 Step 5. Dockerize Your Services
Create Dockerfile in each microservice:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "ProductService.dll"]
Then create docker-compose.yml to run all services:
version: '3.4'
services:
productservice:
build: ./ProductService
ports:
- "5001:80"
orderservice:
build: ./OrderService
ports:
- "5002:80"
Run
docker-compose up --build
🔐 Step 6. Secure Your Microservices
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://auth-server";
options.Audience = "product-api";
});
📈 Step 7. Observability and Monitoring
-
Logging: Serilog, ELK, or Seq.
-
Tracing: OpenTelemetry, Jaeger.
-
Health Checks:
builder.Services.AddHealthChecks();
app.MapHealthChecks("/health");
📦 Step 8. Deploy with Kubernetes (Optional)
If scaling is needed:
-
Write Deployment.yaml for each service.
-
Use kubectl apply -f deployment.yaml.
-
Use Ingress + Service mesh (like Istio) for routing and monitoring.
✅ Conclusion
Creating microservices in .NET involves:
-
Building independent ASP.NET Core APIs.
-
Managing communication via REST, gRPC, or messaging.
-
Containerizing and orchestrating using Docker and Kubernetes.
-
Securing and monitoring services for production readiness.
With this foundation, you can build scalable, maintainable microservices using the powerful .NET ecosystem.