A production-ready Clean Architecture template for .NET microservices implementing CQRS, MediatR, FastEndpoints, and Entity Framework Core. Includes complete project structure with API, Application, Core, and Infrastructure layers, plus comprehensive test coverage.
$ dotnet add package Miccore.Net.CleanArchitectureTemplate🚀 Template de microservice Clean Architecture avec fournisseur de base de données MySQL
🚀 Template de microservice Clean Architecture avec fournisseur de base de données PostgreSQL
🚀 Template de microservice Clean Architecture avec fournisseur de base de données SQL Server
Ce projet est basé sur le template Miccore Clean Architecture qui implémente les meilleures pratiques d'architecture logicielle pour les microservices .NET.
Si vous souhaitez créer de nouveaux projets à partir de ce template :
# Installer le template depuis NuGet
dotnet new install Miccore.Net.CleanArchitectureTemplate
# Créer un nouveau projet (nom simple)
dotnet new miccore-clean -n MonProjet
# Créer un nouveau projet (nom composé - recommandé)
dotnet new miccore-clean -n Acme.Ecommerce.Catalog
# Avec PostgreSQL au lieu de MySQL
dotnet new miccore-clean -n MonProjet --databaseProvider PostgreSQL
# Voir tous les paramètres disponibles
dotnet new miccore-clean --help
| Paramètre | Type | Valeur par défaut | Description |
|---|---|---|---|
--databaseProvider | choice | MySQL | Fournisseur de base de données : MySQL, PostgreSQL, ou SqlServer |
Pour les projets d'entreprise, nous recommandons d'utiliser un format en 3 parties :
Company.Service.ComponentAcme.Ecommerce.CatalogContoso.Crm.ApiFabrikam.Inventory.ServiceLes noms simples sont également acceptés (exemple : MonProjet), mais le format composé améliore l'organisation dans les grandes structures.
Le projet suit les principes de la Clean Architecture (Architecture Hexagonale / Onion Architecture) pour assurer une séparation claire des responsabilités, une testabilité accrue et une indépendance vis-à-vis des frameworks externes.
Miccore.Clean.Sample/
├── 📁 src/
│ ├── 📁 Miccore.Clean.Sample.Api/ # Point d'entrée REST API
│ │ ├── Configuration/ # Config (Serilog, Swagger, DI)
│ │ ├── Endpoints/ # FastEndpoints (REPR pattern)
│ │ │ └── BaseEndpoint.cs
│ │ ├── Features/
│ │ │ └── Samples/ # Endpoints par feature
│ │ ├── Middleware/ # Exception, CorrelationId
│ │ └── Program.cs
│ │
│ ├── 📁 Miccore.Clean.Sample.Application/ # Logique métier (Use Cases)
│ │ ├── Behaviors/ # MediatR Pipelines
│ │ │ ├── LoggingBehavior.cs
│ │ │ └── ValidationBehavior.cs
│ │ ├── Features/
│ │ │ └── Samples/
│ │ │ ├── Commands/ # Create, Update, Delete
│ │ │ │ └── CreateSample/
│ │ │ │ ├── CreateSampleCommand.cs
│ │ │ │ ├── CreateSampleCommandHandler.cs
│ │ │ │ └── CreateSampleValidator.cs
│ │ │ ├── Queries/ # Get, GetAll
│ │ │ │ └── GetAllSamples/
│ │ │ │ ├── GetAllSamplesQuery.cs
│ │ │ │ └── GetAllSamplesQueryHandler.cs
│ │ │ ├── Mappers/
│ │ │ └── Responses/
│ │ └── Handlers/ # Base handlers (Command/Query)
│ │
│ ├── 📁 Miccore.Clean.Sample.Core/ # Domaine (aucune dépendance)
│ │ ├── ApiModels/ # ApiResponse<T>, ApiError
│ │ ├── Entities/ # BaseEntity, SampleEntity
│ │ ├── Exceptions/ # NotFoundException, ValidatorException
│ │ ├── Interfaces/ # IUnitOfWork, ICacheService
│ │ └── Repositories/
│ │ ├── Base/
│ │ │ ├── IReadOnlyRepository.cs # Queries (ISP)
│ │ │ └── IBaseRepository.cs # Commands (hérite IReadOnlyRepository)
│ │ └── ISampleRepository.cs
│ │
│ └── 📁 Miccore.Clean.Sample.Infrastructure/ # Implémentation technique
│ ├── Caching/
│ │ ├── MemoryCacheService.cs
│ │ └── CachedRepositoryDecorator.cs # Decorator Pattern
│ ├── Persistence/
│ │ ├── SampleApplicationDbContext.cs
│ │ └── UnitOfWork.cs
│ └── Repositories/
│ ├── Base/
│ │ └── BaseRepository.cs
│ └── SampleRepository.cs
│
├── 📁 test/
│ ├── Miccore.Clean.Sample.Api.Tests/
│ ├── Miccore.Clean.Sample.Application.Tests/
│ ├── Miccore.Clean.Sample.Core.Tests/
│ └── Miccore.Clean.Sample.Infrastructure.Tests/
│
├── 📁 .github/
│ ├── workflows/
│ │ ├── ci.yml # Build, Test, Code Quality, Security
│ │ ├── pr-check.yml # PR validation + Auto-labeling
│ │ └── dependency-review.yml
│ └── labeler.yml
│
├── .editorconfig
├── Directory.Build.props
├── Dockerfile
└── Miccore.Clean.Sample.sln
La solution est divisée en 4 couches principales :
Miccore.Clean.Sample.Core) : Le cœur du domaine.Miccore.Clean.Sample.Application) : La logique métier et les cas d'utilisation.Miccore.Clean.Sample.Infrastructure) : L'implémentation technique (BDD, Cache, etc.).Miccore.Clean.Sample.Api) : Le point d'entrée de l'application (REST API).Cette couche ne dépend d'aucun autre projet. Elle contient :
SampleEntity).IReadOnlyRepository<T> : Opérations de lecture seule (ISP).IBaseRepository<T> : Opérations CRUD (hérite de IReadOnlyRepository).IUnitOfWork : Gestion des transactions.ICacheService : Abstraction du cache.NotFoundException, ValidatorException).ApiResponse<T>, ApiError).Cette couche orchestre la logique métier. Elle dépend de Core.
IReadOnlyRepository<T> (lecture seule).IUnitOfWork.Features/Samples/Commands/CreateSample).ValidationBehavior : Valide automatiquement les requêtes via FluentValidation.LoggingBehavior : Loggue les entrées/sorties et les performances.BaseCommandHandler et BaseQueryHandler pour standardiser le traitement.Cette couche implémente les interfaces définies dans Core. Elle dépend de Core.
SampleApplicationDbContext.UnitOfWork gère les transactions et expose SaveChangesAsync.BaseRepository<T> : Implémentation générique CRUD (implémente IBaseRepository<T>).SampleRepository : Implémentation spécifique.MemoryCacheService : Wrapper autour de IMemoryCache.CachedRepositoryDecorator<T> : Implémente le pattern Decorator pour ajouter du cache (Cache-Aside) de manière transparente aux repositories.Le point d'entrée HTTP. Elle dépend de Application et Infrastructure.
ExceptionHandlingMiddleware : Capture globale des erreurs et formatage en ProblemDetails.CorrelationIdMiddleware : Ajoute un ID unique à chaque requête pour le traçage (Log Context).Prenons l'exemple d'une création (CreateSample) :
POST /api/samples.CorrelationIdMiddleware génère un ID de trace.ExceptionHandlingMiddleware enveloppe l'exécution.CreateSampleEndpoint reçoit la requête (CreateSampleRequest).CreateSampleCommand.LoggingBehavior loggue le début.ValidationBehavior exécute CreateSampleValidator. Si invalide -> ValidatorException.CreateSampleCommandHandler traite la commande.
ISampleRepository.AddAsync.IUnitOfWork.SaveChangesAsync pour persister.SampleResponse.SampleRepository (via BaseRepository) prépare l'entité pour EF Core.SaveChangesAsync.IUnitOfWork pour persister.IReadOnlyRepository<T> (lecture seule).MediatR pour découpler l'émetteur (Endpoint) du traitant (Handler).SaveChangesAsync directement.IReadOnlyRepository<T> : Méthodes de lecture (GetAllAsync, GetByIdAsync, etc.).IBaseRepository<T> : Hérite de IReadOnlyRepository + méthodes d'écriture (AddAsync, UpdateAsync, DeleteAsync).IReadOnlyRepository<T> et IBaseRepository<T>.CachedRepositoryDecorator) permet d'ajouter du cache sans modifier le code métier ni le repository SQL.
Request), sa réponse (Response) et sa méthode HandleAsync.try/catch dans les contrôleurs/endpoints.NotFoundException, ValidatorException) sont lancées par le Core/Application.Le projet inclut une suite de tests complète :
# Exécuter tous les tests
dotnet test
# Avec rapport de couverture
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
# Exécuter les tests d'un projet spécifique
dotnet test test/Miccore.Clean.Sample.Application.Tests
Objectif de couverture : > 70%
src/Miccore.Clean.Sample.Api/appsettings.json :{
"DatabaseConfiguration": {
"Server": "localhost",
"Port": 3306,
"Database": "votre_base_de_donnees",
"UserId": "votre_utilisateur",
"Password": "votre_mot_de_passe"
}
}
{
"DatabaseConfiguration": {
"Server": "localhost",
"Port": 5432,
"Database": "votre_base_de_donnees",
"UserId": "votre_utilisateur",
"Password": "votre_mot_de_passe"
}
}
{
"DatabaseConfiguration": {
"Server": "localhost",
"Port": 1433,
"Database": "votre_base_de_donnees",
"UserId": "votre_utilisateur",
"Password": "votre_mot_de_passe"
}
}
# Créer la première migration
dotnet ef migrations add InitialCreate --project src/Miccore.Clean.Sample.Infrastructure --startup-project src/Miccore.Clean.Sample.Api
# Appliquer la migration à la base de données
dotnet ef database update --project src/Miccore.Clean.Sample.Infrastructure --startup-project src/Miccore.Clean.Sample.Api
💡 Note : Consultez DatabaseProviderConfiguration.md pour des exemples détaillés de configuration selon votre fournisseur de base de données, y compris les différences de comportement et les meilleures pratiques.
# Restaurer les dépendances
dotnet restore
# Compiler la solution
dotnet build
# Lancer l'API
dotnet run --project src/Miccore.Clean.Sample.Api
L'API sera accessible à l'adresse : https://localhost:5001 (ou le port configuré)
En mode Development, Swagger est accessible via :
https://localhost:5001/swagger# Construire l'image
docker build -t miccore-clean-sample .
# Lancer le conteneur
docker run -p 8080:8080 miccore-clean-sample
Ce projet respecte les 5 principes SOLID :
| Principe | Application |
|---|---|
| SRP | Un handler par commande/requête, un endpoint par action |
| OCP | Behaviors MediatR, Decorator pour le cache |
| LSP | Tous les repositories sont interchangeables via leurs interfaces |
| ISP | IReadOnlyRepository vs IBaseRepository, interfaces spécifiques par feature |
| DIP | Injection de dépendances partout, aucune dépendance concrète dans Application/Core |
Ce projet est un template. Pour contribuer au template lui-même :
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Ce projet est sous licence MIT. Voir le fichier LICENSE pour plus de détails.
Généré avec le template Miccore Clean Architecture 🚀