Skip to content

parisxmas/DotNetCleanCode

Repository files navigation

Clean Architecture Microservices

A comprehensive microservices architecture implementation using .NET 8 with Clean Architecture principles, DDD patterns, and reliable messaging.

Architecture Overview

This solution demonstrates a production-ready microservices architecture with:

  • Clean Architecture - Separation of concerns with Domain, Application, Infrastructure, and API layers
  • Domain-Driven Design - Aggregate roots, entities, value objects, and domain events
  • CQRS - Command Query Responsibility Segregation using MediatR
  • Event-Driven Architecture - Asynchronous communication via RabbitMQ and MassTransit
  • Outbox/Inbox Patterns - Reliable messaging with guaranteed delivery and idempotency
  • Microservices - Independent, deployable services with their own databases

Services

Identity Service (Port 5168)

  • User registration and authentication
  • JWT token generation and validation
  • Refresh token support
  • ASP.NET Core Identity with PostgreSQL

Basket Service (Port 5169)

  • Shopping basket management
  • Redis-based storage for fast access
  • JWT authentication required
  • User-specific basket isolation

Product Service (Port 5165)

  • Product catalog management
  • PostgreSQL database
  • Event publishing for product changes
  • CQRS with MediatR

Order Service (Port 5166)

  • Order processing
  • Event-driven communication
  • Consumes product and payment events

Payment Service (Port 5167)

  • Payment processing
  • Event-driven communication
  • Publishes payment events

Infrastructure

BuildingBlocks Library

Shared library containing:

  • Domain primitives (Entity, ValueObject, AggregateRoot)
  • Integration event base classes
  • Outbox pattern implementation
  • Inbox pattern implementation
  • Idempotent consumer base class

Databases

  • PostgreSQL - Product service and Identity service
  • Redis - Basket service (in-memory storage)

Message Broker

  • RabbitMQ - Event-driven communication between services

Getting Started

Prerequisites

  • Docker and Docker Compose
  • .NET 8 SDK (for local development)

Running with Docker Compose

  1. Clone the repository
  2. Navigate to the project root
  3. Start all services:
docker-compose up --build

This will start:

  • PostgreSQL (port 5433)
  • Redis (port 6379)
  • RabbitMQ (ports 5672, 15672)
  • Identity Service (port 5168)
  • Basket Service (port 5169)
  • Product Service (port 5165)
  • Order Service (port 5166)
  • Payment Service (port 5167)

Access Points

Usage Example

1. Register a User

curl -X POST http://localhost:5168/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "Password123!",
    "userName": "johndoe"
  }'

2. Login

curl -X POST http://localhost:5168/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "Password123!"
  }'

Response includes accessToken and refreshToken.

3. Add Item to Basket

curl -X POST http://localhost:5169/api/basket/{userId}/items \
  -H "Authorization: Bearer {accessToken}" \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "product-123",
    "productName": "Sample Product",
    "price": 29.99,
    "quantity": 2
  }'

4. Get Basket

curl -X GET http://localhost:5169/api/basket/{userId} \
  -H "Authorization: Bearer {accessToken}"

Project Structure

CleanArch.sln
├── CleanArch.BuildingBlocks/          # Shared library
│   ├── Domain/                        # Domain primitives
│   ├── IntegrationEvents/             # Event base classes
│   ├── Outbox/                        # Outbox pattern
│   └── Inbox/                         # Inbox pattern
├── CleanArch.Identity.Api/            # Identity service
├── CleanArch.Basket.Api/              # Basket service
├── CleanArch.Api/                     # Product service
├── CleanArch.Order.Api/               # Order service
├── CleanArch.Payment.Api/             # Payment service
├── CleanArch.Domain/                  # Domain layer
├── CleanArch.Application/             # Application layer
├── CleanArch.Infrastructure/          # Infrastructure layer
├── CleanArch.Contracts/               # Shared contracts
└── docker-compose.yml                 # Docker orchestration

Patterns Implemented

Outbox Pattern

Ensures reliable message publishing by storing events in the database before publishing to the message broker. A background service polls for unprocessed messages and publishes them.

Benefits:

  • Guaranteed message delivery
  • Transactional consistency
  • Resilience to message broker failures

Inbox Pattern

Ensures idempotent message processing by tracking processed message IDs. Duplicate messages are automatically ignored.

Benefits:

  • Prevents duplicate processing
  • Handles message redelivery
  • Maintains data consistency

CQRS

Separates read and write operations using MediatR commands and queries.

Benefits:

  • Optimized read/write models
  • Scalability
  • Clear separation of concerns

Configuration

JWT Settings

All services use the same JWT configuration for authentication:

{
  "Jwt": {
    "Secret": "YourSuperSecretKeyThatIsAtLeast32CharactersLong!",
    "Issuer": "CleanArch.Identity",
    "Audience": "CleanArch.Api",
    "ExpiryMinutes": "60"
  }
}

Important: Change the JWT secret in production!

Database Connections

Services use environment variables for database connections (configured in docker-compose.yml):

  • Product Service: Host=postgres;Port=5432;Database=CleanArchDb
  • Identity Service: Host=postgres;Port=5432;Database=CleanArchIdentityDb
  • Basket Service: redis:6379

Development

Building Locally

dotnet build CleanArch.sln

Running Tests

dotnet test CleanArch.UnitTests/CleanArch.UnitTests.csproj

Running Individual Services

# Identity Service
dotnet run --project CleanArch.Identity.Api/CleanArch.Identity.Api.csproj

# Basket Service
dotnet run --project CleanArch.Basket.Api/CleanArch.Basket.Api.csproj

# Product Service
dotnet run --project CleanArch.Api/CleanArch.Api.csproj

Next Steps

To complete the Outbox/Inbox integration:

  1. Add OutboxMessage and InboxMessage DbSets to existing service DbContexts
  2. Register OutboxRepository and InboxRepository in service DI containers
  3. Register OutboxProcessorService as a hosted service
  4. Update event publishers to use the Outbox pattern
  5. Update consumers to inherit from IdempotentConsumer<T>
  6. Run database migrations to create Outbox/Inbox tables

See the walkthrough document for detailed integration steps.

License

This project is for educational and demonstration purposes.

About

.Net Clean Code template with DDD

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors