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

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors