Ching.Dapper.Clean.Solution.Template 1.1.3

dotnet new install Ching.Dapper.Clean.Solution.Template::1.1.3
                    
This package contains a .NET Template Package you can call from the shell/command line.

Dapper Clean Architecture Solution Template

NuGet Downloads License: MIT

Plantilla dotnet new que genera una solución .NET 10 con Clean Architecture y Dapper, lista para producción. Auth completa (JWT + refresh + roles dinámicos), seguridad endurecida, observabilidad, y módulos opcionales — todo configurable al crear el proyecto.

dotnet new install Ching.Dapper.Clean.Solution.Template
dotnet new dapper-solution -n MyProject

Por qué esta plantilla

Sin plantilla Con esta plantilla
Auth básico (JWT firmado + verify) 2 días de research + bugs Ya viene, probado
Refresh tokens rotativos Otro día Incluido
Logout que mata el JWT al instante Casi nadie lo implementa Blocklist JTI + cache
Roles dinámicos + permisos por endpoint 3 días [HasPermission("...")] y listo
Account lockout, CSRF, security headers, HSTS, CORS allowlist, rate limit "Lo agregamos después" (nunca) Configurado de fábrica
Health checks, logs estructurados, OpenTelemetry, Prometheus 1 día por pieza Cableado
Estructura limpia que escala Discusiones eternas Domain · Application · Infrastructure · Api

No es opinated por opinated — es lo que debería estar en una API productiva del día 1.


Quick start (5 minutos)

# 1. Instalar plantilla
dotnet new install Ching.Dapper.Clean.Solution.Template

# 2. Generar proyecto
dotnet new dapper-solution -n Acme.Catalog \
  --companyName "ACME" \
  --companyEmail "dev@acme.io" \
  --apiDocName "CATALOG" \
  --dbName "acme_catalog"

cd Acme.Catalog

# 3. Configurar secreto JWT (mínimo 32 chars, NO commitear)
dotnet user-secrets init --project Acme.Catalog.Api
dotnet user-secrets set "Jwt:Secret" "$(((1..48 | ForEach-Object {[char]((33..126)|Get-Random)}) -join ''))" \
  --project Acme.Catalog.Api

# 4. Aplicar esquema (DBA o pipeline; aquí mostramos manual)
for f in Database/*.sql; do mysql -u root -p acme_catalog < $f; done

# 5. Arrancar
dotnet run --project Acme.Catalog.Api

Swagger en https://localhost:7009/swagger/index.html. Postman collection en postman/.


Documentación

Cada tema tiene una guía profunda en docs/:

Guía Cuándo leerla
Architecture Cómo está estructurada la solución, qué hace cada capa, cómo crece
Adding a module Tutorial paso a paso: agregar la entidad Orders de cero
Authentication JWT, refresh tokens, logout instantáneo (blocklist), Google OAuth, cookie vs header
Authorization Roles dinámicos, catálogo de permisos, [HasPermission(...)], cómo crear un rol nuevo desde la UI
Security Account lockout, CSRF, security headers, HSTS, rate limiting, password reset, email verification
Configuration Todos los parámetros de plantilla, secciones de appsettings, env vars
Database Scripts SQL, convención sin runner, schema versionado
Observability Logs estructurados, correlation ID, OpenTelemetry, Prometheus, health checks, audit log
Deployment Docker, env vars en producción, reverse proxy, prefijos
FAQ Errores comunes, decisiones de diseño, troubleshooting

¿Qué incluye?

Arquitectura

  • 4 proyectos: *.Domain, *.Application, *.Infrastructure, *.Api
  • BaseEntity con auditoría (Id, CreatedAt, UpdatedAt)
  • RepositoryBase<TEntity, TKey> Dapper con paginación + CancellationToken
  • Auto-registro DI por feature vía IServiceModule (zero-config para módulos nuevos)
  • API versioning /api/v{version}/...
  • Swagger multi-documento configurable
  • ProducesResponseType aplicado por convención global a todos los endpoints

Auth

  • JWT (HMAC-SHA256) + refresh tokens rotativos
  • Logout instantáneo con blocklist de JTI (cache + BD)
  • Toggle --authMode={header|cookie|both} — el back inyecta cookies HttpOnly automáticamente en modo cookie
  • CSRF double-submit en modo cookie
  • Roles dinámicos en BD + catálogo de permisos en código
  • BCrypt para contraseñas, Google OAuth opcional
  • Password reset + email verification (con IEmailSender abstraído)
  • Account lockout (5 intentos = 15 min bloqueado)

Seguridad

  • HTTPS redirect + HSTS (1 año, preload) fuera de Development
  • Security headers: CSP, XFO, COOP, CORP, Referrer-Policy, Permissions-Policy
  • CORS desde allowlist en appsettings
  • Rate limiting built-in: 100 req/min global, 5 req/min en /api/v1/auth/*
  • Validación FluentValidation con filtro global

Operaciones

  • Health checks /health/live y /health/ready con ping MySQL
  • OpenTelemetry tracing + metrics (OTLP exporter)
  • Prometheus scrape en /metrics
  • Logging estructurado JSON (Serilog) + correlation ID propagado
  • Audit log con [Audit("action")] en operaciones sensibles
  • Background service de cleanup (tokens revocados/caducados) cada 6h
  • Soporte de reverse proxy con runtime_prefix (UsePathBase)
  • Dockerfile Linux, usuario no-root, build cacheado por capas
  • GitHub Actions CI workflow

Datos

  • Scripts SQL versionados en Database/ (sin runner — el DBA o pipeline los aplica)
  • MySQL 8.x

Tests

  • xUnit + Testcontainers MySQL + WebApplicationFactory

Parámetros (resumen)

Tabla completa en docs/configuration.md.

dotnet new dapper-solution -n MyProject \
  --authMode {header|cookie|both} \             # default: both
  --dbServer / --dbPort / --dbName / --dbUser \
  --jwtIssuer / --jwtAudience / --jwtExpirationMinutes \
  --companyName / --companyEmail / --apiDocName \
  --googleClientId / --googleClientSecret \
  --runtimePrefix / --environmentName \
  --includeUsers / --includeProducts / --includeAuth \   # toggles de features
  --includeDocker / --includeTests / --includeCI         # toggles de extras

Estructura generada

MyProject/
├── MyProject.Api/                  ← Web host: controllers, middlewares, DI wiring
│   ├── Configuration/              ← ApiGroups, response conventions
│   ├── Controllers/                ← AuthController, UserController, RolesController, ProductsController
│   ├── HostedServices/             ← TokenCleanupService
│   ├── Middlewares/                ← GlobalException, CorrelationId, SecurityHeaders, Validation
│   ├── Modules/                    ← IServiceModule + uno por feature (auto-registro DI)
│   ├── Security/                   ← HasPermission, AuditAttribute, CsrfProtection, AuthCookies
│   ├── Program.cs
│   └── appsettings.json
│
├── MyProject.Application/          ← Reglas de negocio, sin dependencias de infraestructura
│   ├── Common/                     ← ApiResponse, DomainException, PagedResult, ErrorCatalog
│   ├── DTOs/                       ← Requests + Responses
│   ├── Interfaces/                 ← Contratos de repos (IUsersRepository, etc.)
│   ├── Notifications/              ← IEmailSender
│   ├── Profiles/                   ← AutoMapper
│   ├── Security/                   ← Permissions catálogo, JwtSettings, LockoutSettings, ITokenRevocationStore
│   ├── Services/                   ← AuthService, UserService, RoleService, AccountService, ProductService
│   └── Validators/                 ← FluentValidation por DTO
│
├── MyProject.Domain/               ← Entidades puras
│   ├── Common/BaseEntity.cs
│   ├── User.cs, Role.cs, Permission.cs, Product.cs
│   ├── RefreshToken.cs, RevokedToken.cs, LoginAttempt.cs
│   ├── PasswordResetToken.cs, EmailVerificationToken.cs
│   └── AuditEntry.cs
│
├── MyProject.Infrastructure/       ← Implementaciones de IO
│   ├── Data/DbConnectionFactory.cs
│   ├── Notifications/LogEmailSender.cs
│   ├── Repositories/               ← Dapper, todos heredan RepositoryBase o se conectan directo
│   └── Security/                   ← JwtTokenGenerator, TokenRevocationStore
│
├── MyProject.Tests/                ← Tests de integración con Testcontainers
│
├── Database/                       ← 9 scripts SQL (0001-0009) — convención manual, sin runner
├── postman/                        ← Postman collection lista para importar
├── docs/                           ← Documentación por tema
├── .github/workflows/ci.yml        ← CI: build + test + (opcional) push docker
├── Directory.Packages.props        ← Central package management
├── .editorconfig
└── MyProject.slnx

Endpoints (resumen)

# Auth (rate-limited 5 req/min, audit log)
POST /api/v1/auth/login              ← Anónimo
POST /api/v1/auth/refresh            ← Anónimo (acepta cookie o body)
POST /api/v1/auth/logout             ← Autenticado, mata JWT actual + revoca refresh tokens
POST /api/v1/auth/forgot-password    ← Anónimo, envía email con token (no revela existencia)
POST /api/v1/auth/reset-password     ← Anónimo, aplica nuevo password + revoca todas las sesiones
POST /api/v1/auth/verify-email       ← Anónimo
POST /api/v1/auth/resend-verification ← Anónimo
GET  /api/v1/auth/google-login       ← Inicia OAuth flow (si Google está configurado)
GET  /api/v1/auth/google-response    ← Callback

# Users
POST /api/v1/users                   ← Anónimo (register, dispara email verification)
GET  /api/v1/users                   ← [HasPermission(users.read)] paginado
GET  /api/v1/users/{id}              ← [HasPermission(users.read)]
PUT  /api/v1/users/{id}/role         ← [HasPermission(users.write)] (audit)

# Roles (administración dinámica)
GET  /api/v1/roles                   ← [HasPermission(roles.read)]
GET  /api/v1/roles/permissions       ← Catálogo del sistema (para UI con checkboxes)
GET  /api/v1/roles/{id}              ← [HasPermission(roles.read)]
POST /api/v1/roles                   ← [HasPermission(roles.manage)] (audit)
PUT  /api/v1/roles/{id}              ← [HasPermission(roles.manage)] (audit)
DELETE /api/v1/roles/{id}            ← [HasPermission(roles.manage)] (audit)

# Products
GET  /api/v1/products                ← [HasPermission(products.read)] paginado
GET  /api/v1/products/{id}           ← [HasPermission(products.read)]
POST /api/v1/products                ← [HasPermission(products.write)]

# Operaciones
GET  /health/live                    ← Liveness probe
GET  /health/ready                   ← Readiness (incluye ping a MySQL)
GET  /metrics                        ← Prometheus scrape

Requisitos

  • .NET SDK 10
  • MySQL 8.x
  • Docker (opcional)

Licencia

MIT — ver LICENSE.

Autor

Missael Del Jesus Ching Mendez · missael.ching@gamasis.mx

Changelog

Ver CHANGELOG.md.

  • .NETStandard 2.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.1.3 113 5/12/2026
1.1.2 110 5/12/2026
1.1.1 128 5/11/2026
1.1.0 121 5/11/2026
1.0.0 124 3/4/2026