CentimxArchitecture 0.5.0
dotnet add package CentimxArchitecture --version 0.5.0
NuGet\Install-Package CentimxArchitecture -Version 0.5.0
<PackageReference Include="CentimxArchitecture" Version="0.5.0" />
<PackageVersion Include="CentimxArchitecture" Version="0.5.0" />
<PackageReference Include="CentimxArchitecture" />
paket add CentimxArchitecture --version 0.5.0
#r "nuget: CentimxArchitecture, 0.5.0"
#:package CentimxArchitecture@0.5.0
#addin nuget:?package=CentimxArchitecture&version=0.5.0
#tool nuget:?package=CentimxArchitecture&version=0.5.0
CentimxArchitecture
Arquitectura reutilizable para servicios ASP.NET Core sobre .NET 10, SQL Server y Dapper. La solución separa las reglas transversales en paquetes NuGet y deja en cada sistema de negocio únicamente dominio, casos de uso, contratos y adaptadores propios.
La entrada recomendada es el paquete CentimxArchitecture. Esta fachada permite composición modular o registra web, seguridad JWT, acceso a SQL Server, transacciones, observabilidad y caché híbrida/Redis con una sola llamada. Los namespaces y ensamblados conservan el prefijo técnico NFC.Architecture.
Estructura
NFC.Architecture.sln
├─ src/ paquetes NuGet reutilizables
│ ├─ NFC.Architecture.Abstractions resultados, errores y contratos neutrales
│ ├─ NFC.Architecture.Operations handlers y pipeline ordenado de behaviors
│ ├─ NFC.Architecture.Data.Abstractions requests USP y repositorio genérico tipado
│ ├─ NFC.Architecture.Data.SqlServer.Dapper repositorio USP, Dapper, transacciones y health check
│ ├─ NFC.Architecture.Data.Caching caché declarativo de Queries e invalidación de Commands
│ ├─ NFC.Architecture.Migrations.SqlServer migraciones versionadas y controladas
│ ├─ NFC.Architecture.Security.JwtBearer autenticación, autorización y usuario actual
│ ├─ NFC.Architecture.Observability trazas y métricas OpenTelemetry
│ ├─ NFC.Architecture.Caching.Abstractions contrato de caché neutral
│ ├─ NFC.Architecture.Caching.Hybrid caché L1/L2, tags y protección de stampede
│ ├─ NFC.Architecture.Caching.Redis proveedor distribuido Redis opcional
│ ├─ NFC.Architecture.Validation.DataAnnotations validación automática de Application
│ ├─ NFC.Architecture.AspNetCore Problem Details, CORS, límites, OpenAPI y salud
│ ├─ NFC.Architecture.AspNetCore.SqlServer fachada de instalación
│ └─ NFC.Architecture.Testing dobles neutrales para proyectos consumidores
├─ samples/ solución de negocio de referencia
│ ├─ NFC.Architecture.Sample.Application
│ ├─ NFC.Architecture.Sample.Infrastructure
│ └─ NFC.Architecture.Sample.Api
└─ tests/ pruebas unitarias, de arquitectura e integración
La dirección de dependencias esperada en una solución consumidora es:
Api ────────────────┐
│ │ composición y endpoints
├─> Application ──> Domain
├─> Contracts
└─> Infrastructure ──> adaptadores especiales y servicios externos
Domain: proyecto opcional cuando existen agregados, invariantes o comportamiento de dominio real
Application: vertical slices con requests, responses, handlers y requests USP; no conoce Dapper ni ASP.NET Core
Infrastructure: implementa sólo adaptadores especiales; el repositorio USP genérico viene del paquete
Api: es la raíz de composición; no contiene lógica de negocio
Uso desde una solución de negocio
Instale el paquete fachada desde el feed NuGet de la organización:
dotnet add <Proyecto.Api> package CentimxArchitecture --version 0.5.0
El Program.cs del proyecto API queda reducido a la composición:
using NFC.Architecture.AspNetCore.SqlServer;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services
.AddNfcArchitectureBuilder(builder.Configuration, builder.Environment)
.AddWebApi()
.AddOperations(typeof(ApplicationMarker).Assembly)
.AddJwtBearer()
.AddSqlServer()
.AddRedisHybridCache()
.AddObservability();
builder.Services.AddApplication();
builder.Services.AddInfrastructure();
WebApplication app = builder.Build();
app.UseNfcArchitecture();
app.MapControllers();
app.MapNfcArchitectureEndpoints();
app.Run();
Para la instalación completa con los valores predeterminados continúa disponible builder.Services.AddNfcArchitecture(builder.Configuration, builder.Environment).
Cada operación declara explícitamente si es Command o Query, el nombre de su USP y la forma tipada del resultado. Los servicios sólo inyectan ICommandExecutor para escrituras e IQueryExecutor para lecturas; el repositorio, Dapper y los contratos de ejecución de stored procedures quedan detrás de esos ejecutores. Las reglas de negocio pueden componerse con ToResult, Ensure, Map y Bind.
La versión 0.5 mantiene eliminada la ejecución pública de SQL crudo: no expone IDataExecutor, DbCommandSpec ni CommandType.Text. Todo acceso normal a datos pasa por una clase de stored procedure y por un nombre validado antes de abrir la conexión. También agrega un pipeline neutral de handlers y behaviors para políticas transversales sin incorporar reglas de negocio al paquete.
Las operaciones atómicas se delimitan con IUnitOfWork. ExecuteAsync confirma si no hay excepciones; ExecuteResultAsync confirma exclusivamente un Result.Success y revierte automáticamente un Result.Failure. UnitOfWorkOptions permite escoger el aislamiento por caso de uso. Los casos de uso se registran con AddValidatedScoped<TUseCase, TImplementation>() para ejecutar automáticamente sus DataAnnotations.
Consulte el ejemplo ejecutable en samples/NFC.Architecture.Sample.Api, el pipeline de operaciones, la comparación con DigitAI, la guía de adopción, el repositorio genérico de procedimientos, el diseño de casos de uso, la caché, las migraciones, las utilidades de testing y el diseño de validación.
Configuración
Toda la configuración está bajo NfcArchitecture; las cadenas permanecen en ConnectionStrings. El arranque valida combinaciones inseguras o incompletas antes de atender tráfico.
{
"ConnectionStrings": {
"DefaultConnection": "<secret>",
"Redis": "<secret>"
},
"NfcArchitecture": {
"Database": {
"ConnectionStringName": "DefaultConnection",
"CommandTimeoutSeconds": 30,
"EnableRetry": true,
"MaxRetryAttempts": 3,
"RetryDelayMilliseconds": 200,
"TransactionIsolationLevel": "ReadCommitted"
},
"Security": {
"Enabled": true,
"Mode": "ExternalAuthority",
"Authority": "https://identity.example.com",
"Issuer": "https://identity.example.com",
"Audience": "business-api",
"RequireHttpsMetadata": true,
"RequireAuthenticatedUserByDefault": true,
"ClockSkewSeconds": 30
},
"WebApi": {
"Documentation": "DevelopmentOnly",
"AllowedOrigins": [ "https://app.example.com" ],
"AllowAnyOrigin": false,
"AllowCredentials": false,
"ExposedHeaders": [ "Location", "Retry-After" ],
"PreflightMaxAgeSeconds": 600,
"RateLimiting": {
"Enabled": true,
"PermitLimit": 100,
"WindowSeconds": 60,
"QueueLimit": 0,
"PartitionStrategy": "UserOrIp"
}
},
"Observability": {
"Enabled": true,
"OtlpEndpoint": "https://otel-collector.example.com",
"TraceSampleRatio": 0.1
},
"Caching": {
"Enabled": false,
"ConnectionStringName": "Redis",
"InstanceName": "business:",
"KeyPrefix": "business:",
"DefaultTtlSeconds": 300,
"LocalTtlSeconds": 60
},
"Migrations": {
"CommandTimeoutSeconds": 60,
"MigrateOnStartup": false,
"AllowRollback": false,
"LockResource": "CentimxArchitecture:SqlServer:Migrations",
"LockTimeoutSeconds": 60,
"ValidateChecksums": true,
"BaselineMissingChecksums": true
}
}
}
No almacene contraseñas, llaves simétricas ni cadenas productivas en archivos versionados. Use variables de entorno, secretos de desarrollo o el almacén de secretos de la plataforma.
Conexiones y transacciones
- Cada operación autónoma abre una conexión lógica, la usa y la desecha de forma asíncrona. El pool de
Microsoft.Data.SqlClientreutiliza las conexiones físicas; no se comparte unSqlConnectionsingleton. IUnitOfWorkabre una conexión y una transacción explícitas y las reutiliza entre los repositorios llamados dentro de su delegado. Confirma al terminar, revierte ante cualquier excepción y, conExecuteResultAsync, también ante un resultado fallido.- Las transacciones anidadas se rechazan. Una operación debe tener un único propietario transaccional.
ExecuteBatchAsyncejecuta una secuencia tipada dentro de la conexión/transacción ambiente.DbParameters.AddTableeIDbParameterProviderhabilitan TVP sin exponer Dapper niSqlParameter.- Las excepciones SQL se traducen a códigos estables para unicidad, referencias, valores inválidos, timeout, deadlock, indisponibilidad y rechazos del comando.
- Los reintentos sólo se ejecutan para comandos marcados como idempotentes y fuera de una transacción. Nunca se reintenta automáticamente una escritura ni una transacción completa.
- El
CancellationTokende la solicitud llega a apertura de conexión, comandos, lecturas, confirmación y esperas de reintento.
La guía completa de decisiones está en conexiones y transacciones.
Seguridad y operación
- JWT valida emisor, audiencia, firma, vigencia y expiración. El modo recomendado en producción es
ExternalAuthoritycon metadatos HTTPS. - La política de respaldo exige usuario autenticado por defecto cuando la seguridad está habilitada. Los endpoints públicos deben declararse explícitamente anónimos.
- Las excepciones se convierten en RFC 7807 Problem Details sin filtrar detalles internos en producción.
- MVC valida automáticamente DataAnnotations, incluidos parámetros de ruta y cuerpos, mediante un filtro global que no depende de recordar
ModelState.IsValid. Application repite la protección en el proxy del servicio para consumidores no HTTP. - Se incluyen identificador de correlación, CORS restrictivo, rate limiting particionado por usuario/IP con
Retry-After, HSTS/HTTPS,/health/live,/health/ready, OpenAPI y Scalar controlados por ambiente. - OpenTelemetry publica instrumentación ASP.NET Core/HTTP y telemetría de operaciones SQL sin registrar texto SQL ni parámetros.
Compilar, probar y empaquetar
dotnet restore NFC.Architecture.sln
dotnet test NFC.Architecture.sln -c Release
./build/pack.ps1
Para publicar, configure la API key fuera del repositorio y ejecute:
$env:CENTIMX_NUGET_API_KEY = '<api-key>'
./build/publish.ps1
El script publica primero los módulos y al final la fachada CentimxArchitecture; usa --skip-duplicate para permitir reintentos seguros de una misma versión.
El número de versión común se controla con VersionPrefix en Directory.Build.props. Los proyectos de ejemplo y pruebas tienen IsPackable=false; sólo se generan paquetes para los módulos de src. El empaquetado ejecuta Package Validation para detectar incompatibilidades estructurales.
Alcance
El paquete ofrece infraestructura transversal y reglas seguras por defecto. No intenta definir entidades, DTO, nombres de procedimientos, reglas de negocio ni estructura interna de cada caso de uso. Esas decisiones permanecen en la solución consumidora.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- CentimxArchitecture.AspNetCore (>= 0.5.0)
- CentimxArchitecture.Caching.Hybrid (>= 0.5.0)
- CentimxArchitecture.Caching.Redis (>= 0.5.0)
- CentimxArchitecture.Data.Caching (>= 0.5.0)
- CentimxArchitecture.Data.SqlServer.Dapper (>= 0.5.0)
- CentimxArchitecture.Migrations.SqlServer (>= 0.5.0)
- CentimxArchitecture.Observability (>= 0.5.0)
- CentimxArchitecture.Operations (>= 0.5.0)
- CentimxArchitecture.Security.JwtBearer (>= 0.5.0)
- Dapper (>= 2.1.79)
- FluentMigrator.Runner (>= 6.2.0)
- FluentMigrator.Runner.SqlServer (>= 6.2.0)
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 10.0.11)
- Microsoft.AspNetCore.OpenApi (>= 10.0.11)
- Microsoft.Data.SqlClient (>= 7.0.2)
- Microsoft.Extensions.Caching.Hybrid (>= 10.9.0)
- Microsoft.Extensions.Caching.StackExchangeRedis (>= 10.0.11)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.17.0)
- OpenTelemetry.Extensions.Hosting (>= 1.17.0)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.17.0)
- OpenTelemetry.Instrumentation.Http (>= 1.17.0)
- Scalar.AspNetCore (>= 2.16.20)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.