# .NET 10 Microservice Template

> Enterprise-grade .NET 10 microservice template following DDD, CQRS, and Clean Architecture patterns.

## Overview

This template provides a production-ready structure for .NET microservices based on the eShopOnContainers reference architecture with:

- **Domain-Driven Design (DDD)** - Aggregates, Entities, Value Objects, Domain Events
- **CQRS Pattern** - Separate Commands (write) and Queries (read) with MediatR
- **Clean Architecture** - Domain, Infrastructure, API layered separation
- **EF Core 10** - PostgreSQL with connection resilience
- **FluentValidation** - Request validation
- **API Versioning** - URL segment versioning
- **Health Checks** - Kubernetes-ready probes
- **Structured Logging** - Serilog with console and Seq

## Prerequisites

| Requirement | Version |
|-------------|---------|
| .NET SDK | 10.0.101+ |
| Docker | 24.0+ |
| PostgreSQL | 15+ (or use Docker) |

```bash
# Check .NET version
dotnet --version
# Should output: 10.0.xxx
```

## Quick Start

### 1. Create New Service

```bash
# Copy template to new service
cp -r services/_template_dot_net services/your-service-name

# Navigate to service directory
cd services/your-service-name

# Rename all occurrences of "MyService" to "YourService"
find . -type f -name "*.cs" -exec sed -i '' 's/MyService/YourService/g' {} +
find . -type f -name "*.csproj" -exec sed -i '' 's/MyService/YourService/g' {} +
```

### 2. Configure Environment

```bash
# Copy environment template
cp .env.example .env

# Edit with your configuration
nano .env
```

### 3. Run with Docker

```bash
# Start all services (API + PostgreSQL + Redis)
docker-compose up -d

# View logs
docker-compose logs -f myservice-api
```

### 4. Run Locally

```bash
# Restore dependencies
dotnet restore

# Build all projects
dotnet build

# Run the API
dotnet run --project src/MyService.API
```

## Project Structure

```
_template_dot_net/
├── src/
│   ├── MyService.API/              # Presentation Layer (Controllers, CQRS)
│   │   ├── Controllers/            # API endpoints
│   │   ├── Application/            # CQRS Implementation
│   │   │   ├── Commands/           # Write operations (MediatR)
│   │   │   ├── Queries/            # Read operations
│   │   │   ├── Behaviors/          # MediatR pipeline behaviors
│   │   │   └── Validations/        # FluentValidation validators
│   │   ├── Middleware/             # Custom middleware
│   │   └── Program.cs              # Application entry point
│   │
│   ├── MyService.Domain/           # Domain Layer (Pure business logic)
│   │   ├── AggregatesModel/        # Aggregate roots and entities
│   │   ├── Events/                 # Domain events
│   │   ├── Exceptions/             # Domain exceptions
│   │   └── SeedWork/               # Base classes (Entity, ValueObject, etc.)
│   │
│   └── MyService.Infrastructure/   # Infrastructure Layer (Data access)
│       ├── EntityConfigurations/   # EF Core Fluent API configurations
│       ├── Repositories/           # Repository implementations
│       ├── Idempotency/            # Request idempotency handling
│       └── MyServiceContext.cs     # DbContext with Unit of Work
│
├── tests/
│   ├── MyService.UnitTests/        # Unit tests (Domain, Application)
│   └── MyService.FunctionalTests/  # Integration tests (API endpoints)
│
├── Dockerfile                      # Multi-stage Docker build
├── docker-compose.yml              # Local development setup
├── global.json                     # .NET SDK version pinning
└── Directory.Build.props           # Common MSBuild properties
```

## API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/samples` | Get all samples |
| `GET` | `/api/v1/samples/{id}` | Get sample by ID |
| `POST` | `/api/v1/samples` | Create new sample |
| `PUT` | `/api/v1/samples/{id}` | Update sample |
| `DELETE` | `/api/v1/samples/{id}` | Delete sample |
| `PATCH` | `/api/v1/samples/{id}/status` | Change status |

### Health Endpoints

| Endpoint | Purpose |
|----------|---------|
| `/health` | Full health status |
| `/health/live` | Liveness probe |
| `/health/ready` | Readiness probe |

## CQRS Pattern

### Commands (Write Operations)

```csharp
// Define command
public record CreateSampleCommand(string Name, string? Description) 
    : IRequest<CreateSampleCommandResult>;

// Handle command
public class CreateSampleCommandHandler : IRequestHandler<CreateSampleCommand, CreateSampleCommandResult>
{
    public async Task<CreateSampleCommandResult> Handle(CreateSampleCommand request, CancellationToken ct)
    {
        var sample = new Sample(request.Name, request.Description);
        _repository.Add(sample);
        await _repository.UnitOfWork.SaveEntitiesAsync(ct);
        return new CreateSampleCommandResult(sample.Id);
    }
}
```

### Queries (Read Operations)

```csharp
// Define query
public record GetSampleQuery(Guid SampleId) : IRequest<SampleViewModel?>;
```

## Domain Model

### Aggregate Root

```csharp
public class Sample : Entity, IAggregateRoot
{
    public string Name => _name;
    public SampleStatus Status => _status;
    
    public Sample(string name, string? description) {
        // Business logic validation
        if (string.IsNullOrWhiteSpace(name))
            throw new SampleDomainException("Sample name cannot be empty");
        
        // Domain event
        AddDomainEvent(new SampleCreatedDomainEvent(this));
    }
    
    public void Activate() {
        if (_status != SampleStatus.Draft)
            throw new SampleDomainException("Only draft samples can be activated");
        // State transition
    }
}
```

## Testing

```bash
# Run all tests
dotnet test

# Run with coverage
dotnet test /p:CollectCoverage=true /p:CoverageReportFormat=cobertura

# Run specific test project
dotnet test tests/MyService.UnitTests
```

## Configuration

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `ASPNETCORE_ENVIRONMENT` | Environment name | `Development` |
| `DATABASE_URL` | PostgreSQL connection string | - |
| `REDIS_URL` | Redis connection string | - |
| `JWT_SECRET` | JWT signing secret (min 32 chars) | - |

### appsettings.json

```json
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=localhost;Database=myservice;Username=postgres;Password=postgres"
  },
  "Serilog": {
    "MinimumLevel": "Information"
  }
}
```

## Deployment

### Docker Build

```bash
# Build Docker image
docker build -t myservice:latest .

# Run container
docker run -p 5000:8080 --env-file .env myservice:latest
```

### Kubernetes

See [ARCHITECTURE.md](./ARCHITECTURE.md) for Kubernetes deployment manifests.

## What's New in .NET 10

- **C# 14** language features
- Improved **Native AOT** support
- Better **async/await** performance
- Enhanced **JSON serialization**
- Performance improvements across the board
- 3-year **LTS** support (until November 2028)

## Resources

- [eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers) - Reference architecture
- [.NET 10 Documentation](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10)
- [DDD with .NET](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/)
- [MediatR](https://github.com/jbogard/MediatR) - CQRS library
- [FluentValidation](https://docs.fluentvalidation.net/) - Validation library

## License

Proprietary - GoodGo Platform
