Minimdev.CleanArchitecture.Template
1.6.0
dotnet new install Minimdev.CleanArchitecture.Template@1.6.0
Clean Architecture Template Solution (.NET 10)
A comprehensive, production-ready ASP.NET Core starter template implementing Clean Architecture principles with CQRS, MediatR, JWT Authentication, and modern API documentation.
๐๏ธ Project Structure
YourProject/
โโโ src/
โ โโโ Core/
โ โ โโโ YourProject.Domain/ # Enterprise business rules & entities
โ โ โโโ YourProject.Application/ # Use cases, CQRS, validators, interfaces
โ โโโ Infrastructure/
โ โ โโโ YourProject.Infrastructure.Persistence/ # Data access (EF Core, migrations)
โ โ โโโ YourProject.Infrastructure.Identity/ # Authentication & JWT
โ โ โโโ YourProject.Infrastructure.Shared/ # Shared services (email, datetime, etc.)
โ โโโ Presentation/
โ โโโ YourProject.WebAPI/ # REST API controllers, middleware, DI
โ โโโ YourProject.WebUI/ # Blazor Server interactive frontend
โโโ tests/
โ โโโ YourProject.Domain.UnitTests/
โ โโโ YourProject.Application.UnitTests/
โ โโโ YourProject.Application.IntegrationTests/
โโโ docker-compose.yml
โโโ Dockerfile
โโโ YourProject.sln
โโโ README.md
โจ Features
๐๏ธ Architecture & Patterns
- โ Clean Architecture โ Clear layer separation with strict dependency rules
- โ CQRS โ Command Query Responsibility Segregation via MediatR
- โ Domain-Driven Design โ Rich domain models encapsulating business logic
- โ Repository Pattern โ Abstracted data access layer
- โ Result Pattern โ Consistent, explicit error handling without exceptions
โ๏ธ Technology Stack
- โ .NET 10 โ Latest long-term support framework
- โ Blazor Server WebUI โ Interactive frontend with MudBlazor Material Design components
- โ MediatR v12.x โ In-process messaging for CQRS implementation
- โ Entity Framework Core 10 โ Code-First ORM with full migration support
- โ SQL Server โ Separate databases for Application and Identity
- โ ASP.NET Core Identity โ User and role management
- โ JWT Bearer Authentication โ Stateless, secure API authentication
- โ Mapster v10.x โ High-performance object-to-object mapping
- โ FluentValidation โ Expressive and testable request validation
- โ
Scalar UI โ Modern API documentation with JWT support (fully offline โ
scalar.min.jsis bundled as a local static file with proxy and telemetry disabled) - โ OpenTelemetry โ Distributed tracing and observability (Console + OTLP exporters)
- โ xUnit โ Unit and integration testing framework
๐ Key Capabilities
- โ
Refresh Token โ Secure token rotation with
POST /api/v1/Auth/refreshand revoke viaPOST /api/v1/Auth/revoke - โ
Integration Tests โ
WebApplicationFactorywith SQLite in-memory, no SQL Server required for testing - โ
Role-Based Access Control (RBAC) โ Pre-configured
AdminandMemberroles with authorization policies - โ User Management Dashboard โ View users and modify roles dynamically from the UI
- โ
API Versioning โ Versioned endpoints (
/api/v1/...) via URL segment & request header - โ Rate Limiting โ Built-in ASP.NET Core rate limiting (global & auth-specific limits)
- โ Response Caching โ Output caching configured for GET endpoints
- โ
Background Jobs โ Hangfire integration with SQL Server storage &
/hangfiredashboard - โ Message Bus (MassTransit) โ Async messaging with switchable transports: InMemory (default), RabbitMQ, ActiveMQ โ enabled via single config line
- โ
Resilience (Polly) โ Retry and circuit-breaker policies via
Microsoft.Extensions.Http.Resilience - โ
Email Service โ
IEmailServiceabstraction with built-inSmtpEmailServiceimplementation - โ
Audit Trails โ Automatic tracking of
CreatedAt/ModifiedAttimestamps - โ Soft Delete โ Global EF Core query filters for logical record deletion
- โ Health Checks โ Database connectivity monitoring endpoint
- โ Global Exception Handling โ Centralized middleware for consistent error responses
- โ CORS Support โ Configurable cross-origin resource sharing
- โ
Docker Support โ Containerization-ready with
Dockerfileanddocker-compose.yml - โ Visual Studio 2022 & 2026 โ Full IDE support via the New Project dialog
- โ .editorconfig โ Comprehensive code style and formatting rules
๐ฆ Using as a Template
Install from NuGet
dotnet new install Minimdev.CleanArchitecture.Template
Create a New Project
Via CLI
# Syntax: dotnet new cleanarch -n [YourProjectName] -o [OutputDirectory]
dotnet new cleanarch -n MyProject -o MyProject
What happens automatically on project creation:
| Original | Replaced With |
|---|---|
CleanArchitecture.Domain |
MyProject.Domain |
namespace CleanArchitecture.Domain |
namespace MyProject.Domain |
src/Core/CleanArchitecture.Domain/ |
src/Core/MyProject.Domain/ |
Via Visual Studio 2022 / 2026
- Open Visual Studio 2022 or Visual Studio 2026
- Click Create a new project
- Search for "Clean Architecture Solution"
- Select the template, enter your project name โ Create
The template automatically renames all projects and namespaces to match your chosen project name.
Uninstall Template
dotnet new uninstall Minimdev.CleanArchitecture.Template
๐ Quick Start
A. Template User (Generated Project)
After creating your project from the template (dotnet new cleanarch -n MyProject), replace MyProject with your actual project name in the steps below.
Prerequisites
- .NET 10 SDK
- SQL Server or SQL Server Express
- Visual Studio 2022 / 2026, or VS Code
Setup Steps
1. Update connection strings
Edit src/Presentation/MyProject.WebAPI/appsettings.Development.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyProjectDB;Trusted_Connection=True;TrustServerCertificate=True;",
"IdentityConnection": "Server=localhost;Database=MyProjectIdentityDB;Trusted_Connection=True;TrustServerCertificate=True;",
"HangfireConnection": "Server=localhost;Database=MyProjectHangfireDB;Trusted_Connection=True;TrustServerCertificate=True;"
}
}
2. Apply database migrations
# Application DB
dotnet ef database update \
--project "src/Infrastructure/MyProject.Infrastructure.Persistence" \
--startup-project "src/Presentation/MyProject.WebAPI" \
--context ApplicationDbContext
# Identity DB
dotnet ef database update \
--project "src/Infrastructure/MyProject.Infrastructure.Identity" \
--startup-project "src/Presentation/MyProject.WebAPI" \
--context IdentityDbContext
3. Run the application
dotnet run --project "src/Presentation/MyProject.WebAPI"
4. Access the application
| URL | Description |
|---|---|
https://localhost:{port}/scalar/v1 |
Scalar API Documentation |
https://localhost:{port}/health |
Health Check |
https://localhost:{port}/hangfire |
Hangfire Job Dashboard |
The port number depends on how you run the application:
- CLI (
dotnet run) โ port is defined inProperties/launchSettings.json(default:7253for HTTPS,5022for HTTP) - Visual Studio 2022 / 2026 โ Visual Studio may assign a different port automatically based on the selected launch profile. Check the Output window or browser tab opened by VS for the actual URL.
- To always use a fixed port, set
applicationUrlexplicitly inlaunchSettings.json.
B. Contributor (Template Source)
This section is for contributors who want to develop or modify the template itself.
1. Clone the repository
git clone https://github.com/MinimDev/dotnet-clean-architecture-template.git
cd dotnet-clean-architecture-template
2. Update connection strings
Edit src/Presentation/CleanArchitecture.WebAPI/appsettings.Development.json with your local SQL Server details.
3. Apply migrations
dotnet ef database update \
--project "src/Infrastructure/CleanArchitecture.Infrastructure.Persistence" \
--startup-project "src/Presentation/CleanArchitecture.WebAPI" \
--context ApplicationDbContext
dotnet ef database update \
--project "src/Infrastructure/CleanArchitecture.Infrastructure.Identity" \
--startup-project "src/Presentation/CleanArchitecture.WebAPI" \
--context IdentityDbContext
4. Run
dotnet run --project "src/Presentation/CleanArchitecture.WebAPI"
๐ API Endpoints
Authentication
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/Auth/register |
Register a new user โ returns accessToken + refreshToken |
POST |
/api/v1/Auth/login |
Login โ returns accessToken + refreshToken (Rate limited: 10 req/min) |
POST |
/api/v1/Auth/refresh |
Exchange a valid refresh token for new token pair |
POST |
/api/v1/Auth/revoke |
Revoke refresh token (logout) (Requires Auth) |
Products (Requires Authentication)
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/Products |
Get paginated list (Output Cached: 30s) |
GET |
/api/v1/Products/{id} |
Get product by ID (Output Cached: 60s) |
POST |
/api/v1/Products |
Create a new product |
PUT |
/api/v1/Products/{id} |
Update an existing product |
DELETE |
/api/v1/Products/{id} |
Delete a product |
Background Jobs (Requires Authentication)
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/Jobs/fire-and-forget |
Enqueue an immediate background task |
POST |
/api/v1/Jobs/delayed |
Schedule a delayed background task |
POST |
/api/v1/Jobs/recurring |
Register a CRON-based recurring task |
POST |
/api/v1/Jobs/recurring/trigger |
Trigger the daily recurring task immediately |
Hangfire Dashboard: https://localhost:7253/hangfire
Authenticating in Scalar UI
- Open Scalar UI at
https://localhost:{port}/scalar/v1 - Call
POST /api/v1/Auth/loginand copy the returnedaccessToken - In Scalar UI, click Authentication โ Bearer Token โ paste your
accessToken
Access tokens expire in 15 minutes by default. Use POST /api/v1/Auth/refresh to get a new pair without logging in again.
๐ณ Docker Support
# Build and start all services (API + SQL Server)
docker-compose up -d
# Stop and remove containers
docker-compose down
The API will be available at http://localhost:8080.
๐งช Testing
# Run all tests
dotnet test
# Run with detailed output
dotnet test --logger "console;verbosity=detailed"
๐ง Configuration Reference
Key sections in appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=CleanArchitectureDb;Trusted_Connection=True;TrustServerCertificate=True;",
"IdentityConnection": "Server=localhost;Database=CleanArchitectureIdentityDb;Trusted_Connection=True;TrustServerCertificate=True;",
"HangfireConnection": "Server=localhost;Database=CleanArchitectureHangfireDb;Trusted_Connection=True;TrustServerCertificate=True;"
},
"Jwt": {
"Secret": "your-very-strong-secret-key-min-32-chars",
"Issuer": "CleanArchitecture",
"Audience": "CleanArchitectureUsers",
"AccessTokenExpiryMinutes": 15,
"RefreshTokenExpiryDays": 7
},
"Cors": {
"AllowedOrigins": ["http://localhost:3000", "https://localhost:5001"]
},
"RateLimiting": {
"WindowSeconds": 60,
"PermitLimit": 100,
"Auth": {
"WindowSeconds": 60,
"PermitLimit": 10
}
},
"Email": {
"Host": "smtp.gmail.com",
"Port": 587,
"EnableSsl": true,
"UserName": "your-email@gmail.com",
"Password": "your-app-password",
"From": "your-email@gmail.com",
"DisplayName": "Clean Architecture App"
}
}
Recommended environment variables for production overrides:
ConnectionStrings__DefaultConnection
ConnectionStrings__IdentityConnection
ConnectionStrings__HangfireConnection
Jwt__Secret
Email__Password
๐ Adding New Features
1. Create Entity (Domain Layer)
// src/Core/CleanArchitecture.Domain/Entities/YourEntity.cs
public class YourEntity : BaseAuditableEntity, ISoftDeletable
{
public string Name { get; private set; } = string.Empty;
public static YourEntity Create(string name) =>
new YourEntity { Name = name };
}
2. Add Command & Handler (Application Layer)
// Command
public record CreateYourEntityCommand(string Name) : IRequest<Result<Guid>>;
// Handler
public class CreateYourEntityCommandHandler
: IRequestHandler<CreateYourEntityCommand, Result<Guid>>
{
private readonly IApplicationDbContext _context;
public CreateYourEntityCommandHandler(IApplicationDbContext context)
=> _context = context;
public async Task<Result<Guid>> Handle(CreateYourEntityCommand request, CancellationToken ct)
{
var entity = YourEntity.Create(request.Name);
_context.YourEntities.Add(entity);
await _context.SaveChangesAsync(ct);
return Result<Guid>.Success(entity.Id);
}
}
3. Configure Mapping (Application Layer)
Mapster is configured to auto-scan for IRegister implementations โ simply create the class and it will be picked up automatically.
// src/Core/CleanArchitecture.Application/Features/YourFeature/Mappings/YourEntityMapping.cs
public class YourEntityMapping : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<YourEntity, YourEntityDto>()
.Map(dest => dest.CustomProperty, src => src.Calculation())
.IgnoreNullValues(true);
}
}
4. Create Controller (Presentation Layer)
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
[Authorize]
public class YourController : ControllerBase
{
private readonly IMediator _mediator;
public YourController(IMediator mediator) => _mediator = mediator;
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateYourEntityCommand command)
{
var result = await _mediator.Send(command);
return result.IsSuccess ? Ok(result) : BadRequest(result);
}
}
5. Add MassTransit Consumer (Messaging Layer)
Contoh: react terhadap Domain Event yang dipublish secara otomatis oleh MediatR Pipeline DomainEventPublishingBehaviour setelah entitas sukses tersimpan.
// src/Infrastructure/YourProject.Infrastructure.Messaging/Consumers/YourEntityCreatedConsumer.cs
public sealed class YourEntityCreatedConsumer : IConsumer<YourEntityCreatedEvent>
{
private readonly IBackgroundJobClient _hangfire;
private readonly ILogger<YourEntityCreatedConsumer> _logger;
public YourEntityCreatedConsumer(IBackgroundJobClient hangfire, ILogger<YourEntityCreatedConsumer> logger)
{
_hangfire = hangfire;
_logger = logger;
}
public Task Consume(ConsumeContext<YourEntityCreatedEvent> context)
{
_logger.LogInformation("Received: {Id}", context.Message.EntityId);
// Handoff ke Hangfire untuk proses berat (retry-able, persistent)
// _hangfire.Enqueue<INotificationService>(s =>
// s.SendCreatedNotificationAsync(context.Message.EntityId, CancellationToken.None));
return Task.CompletedTask;
}
}
Auto-discovery: MassTransit akan otomatis menemukan semua class
IConsumer<T>di projectInfrastructure.Messagingโ tidak perlu register manual. Dan setiap entitas yang didaftarkan event-nya viaAddDomainEvent()akan dipublish otomatis tanpa kode tambahan di Handler Anda!
6. Switch Message Transport
Ubah satu baris di appsettings.json:
{
"MassTransit": {
"Transport": "RabbitMQ" // InMemory | RabbitMQ | ActiveMQ
}
}
Atau via environment variable:
MassTransit__Transport=RabbitMQ
MassTransit__RabbitMQ__Host=my-rabbit-server
๐ Security Checklist (Before Production)
โ ๏ธ Do not deploy with default development settings.
- Change JWT Secret โ Use a cryptographically strong secret (min 32 characters)
- Update Connection Strings โ Use secure, dedicated production database credentials
- Enable HTTPS โ Ensure TLS is properly configured and enforce HTTPS redirection
- Restrict CORS Origins โ Allow only known, trusted origins
- Review Password Policies โ Customize in
Infrastructure.Identity/DependencyInjection.cs - Secure Hangfire Dashboard โ Restrict access to authenticated admin users only
- Rotate Secrets Regularly โ Implement a secrets management strategy (e.g., Azure Key Vault)
๐ Architecture Overview
| Layer | Project Suffix | Responsibility |
|---|---|---|
| Domain | *.Domain |
Entities, value objects, domain events, business rules |
| Application | *.Application |
Use cases, CQRS handlers, validators, interfaces, message contracts |
| Persistence | *.Infrastructure.Persistence |
EF Core, DbContext, migrations, repositories |
| Identity | *.Infrastructure.Identity |
ASP.NET Core Identity, JWT token service |
| Shared | *.Infrastructure.Shared |
Cross-cutting services (email, datetime, background queue) |
| Messaging | *.Infrastructure.Messaging |
MassTransit bus, consumers, transport configuration |
| WebAPI | *.WebAPI |
REST controllers, middleware pipeline, DI configuration |
| WebUI | *.WebUI |
Blazor Server interactive frontend |
๐ค Contributing
Contributions are very welcome! Please follow the steps below:
- Fork the repository
- Create your feature branch:
git checkout -b feature/AmazingFeature - Commit your changes:
git commit -m 'feat: add amazing feature' - Push to the branch:
git push origin feature/AmazingFeature - Open a Pull Request on GitHub
๐ License
This project is licensed under the MIT License. See LICENSE for details.
๐ Acknowledgments
- Clean Architecture by Robert C. Martin (Uncle Bob)
- Ardalis CleanArchitecture by Steve Smith
- Jason Taylor's CleanArchitecture by Jason Taylor
Built with โค๏ธ by MinimDev
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.6.0 | 171 | 8/13/2026 |
| 1.5.3 | 285 | 5/26/2026 |
| 1.5.2 | 285 | 4/29/2026 |
| 1.5.1 | 398 | 4/17/2026 |
| 1.4.0 | 314 | 4/6/2026 |
| 1.3.1 | 312 | 4/1/2026 |
| 1.3.0 | 347 | 2/23/2026 |
| 1.2.0 | 337 | 2/20/2026 |
| 1.1.4 | 343 | 2/19/2026 |
| 1.1.3 | 342 | 2/19/2026 |
| 1.1.1 | 352 | 2/19/2026 |
| 1.1.0 | 332 | 2/19/2026 |
| 1.0.9 | 345 | 2/19/2026 |
| 1.0.8 | 348 | 2/18/2026 |
| 1.0.7 | 335 | 2/18/2026 |
| 1.0.6 | 335 | 2/18/2026 |
| 1.0.5 | 339 | 2/18/2026 |
| 1.0.4 | 337 | 2/18/2026 |
| 1.0.3 | 342 | 2/18/2026 |
| 1.0.2 | 332 | 2/18/2026 |
v1.6.0: Added MassTransit Message Bus with Auto-Publish MediatR Behaviour, transport switching (InMemory, RabbitMQ, ActiveMQ), and patched critical transitive vulnerabilities.