.NET
Contenedores y despliegue
- Docker
- Containerize an app with Docker tutorial - .NET-build-containertabs=windows&pivots=dotnet-9-0
- Buenas prácticas al contenerizar apps .NET
- Usa imágenes base oficiales de .NET (runtime y SDK separadas).
- Implementa multi-stage builds para reducir el tamaño de la imagen.
- Define variables de entorno para
ASPNETCORE_ENVIRONMENTy logging. - Utiliza
ENTRYPOINTyCMDcorrectamente para servicios y tareas programadas. - Gestiona secrets con herramientas como
Docker secrets,Azure Key VaultoAWS Secrets Manager.
- Integración con CI/CD
- Usa GitHub Actions o Azure Pipelines para automatizar el build y push al registry.
- Escanea vulnerabilidades en imágenes con herramientas como
trivyodockle.
Hojas de cálculo y automatización
- visual basic VBA
-
[Aspose.Cells for .NET Documentation](https://docs.aspose.com/cells/net/) - ClosedXML - GitHub
- app para exportar a excel con plantillas angular, net y cell 🔥
Librerías y frameworks destacados
- Aspose.Cells for .NET
- Permite crear, leer y modificar archivos Excel programáticamente.
- Soporta fórmulas, gráficos, pivot tables y estilos complejos.
- Ideal para automatización de reportes o generación de hojas de cálculo sin depender de Excel instalado.
- ClosedXML
- API fluida y sencilla sobre OpenXML.
- Permite manejar
.xlsxy.xlsmcon enfoque declarativo. - Ejemplo básico:
using ClosedXML.Excel;
var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Datos");
worksheet.Cell(1, 1).Value = "Nombre";
worksheet.Cell(1, 2).Value = "Edad";
worksheet.Cell(2, 1).Value = "Eduardo";
worksheet.Cell(2, 2).Value = 29;
workbook.SaveAs("Reporte.xlsx");
```
- **VBA (Visual Basic for Applications)**
- Permite automatizar tareas dentro de Excel u Office.
- Combinable con .NET a través de COM Interop o scripts externos.
- Ejemplo: desde .NET, ejecutar macro VBA existente:
```csharp
var excelApp = new Microsoft.Office.Interop.Excel.Application();
var workbook = excelApp.Workbooks.Open("C:\\reportes\\macro.xlsm");
excelApp.Run("ActualizarDatos");
workbook.Close(true);
excelApp.Quit();
```
### Integración de .NET con Excel
- Exportar datos desde aplicaciones .NET (ej. ASP.NET, MAUI o WinForms) a plantillas Excel.
- Uso de librerías para reportes con estilos corporativos.
- Automatización de tareas repetitivas (generar reportes diarios, leer inventarios, procesar celdas).
- Integración con Angular o frontend SPA:
- Backend .NET genera el archivo Excel.
- Angular descarga el archivo con `FileSaver.js` o similar.
- Ideal para sistemas administrativos o ERP modulares.
## Ampliaciones y temas relacionados
- Entity Framework Core para acceso a datos en entornos .NET.
- Blazor como alternativa web a Angular/React en ecosistema .NET.
- Testing en .NET (xUnit, NUnit, Moq).
- [CICD](/devops/cicd/) para pipelines automatizados.
- Microservicios con .NET usando gRPC o REST.
- Performance y profiling .NET con herramientas como dotTrace y BenchmarkDotNet.
---
# .NET — Ampliación de conceptos avanzados
## Arquitectura y diseño avanzado
- **Patrones de arquitectura aplicados a .NET**
- **Clean Architecture** y **Onion Architecture**: separan las capas de dominio, aplicación e infraestructura, facilitando el mantenimiento y los tests.
- **Domain-Driven Design (DDD)**: organiza el código alrededor del dominio empresarial.
- Uso de **Value Objects**, **Entities**, **Aggregates**, **Repositories** y **Domain Events**.
- Compatible con **CQRS** y **Event Sourcing** para separación de lectura/escritura y auditoría histórica.
- **Microservicios con .NET**:
- Comunicación con [gRPC](/backend/grpc/) o mensajería (RabbitMQ, Azure Service Bus).
- Uso de **API Gateway** (Ocelot, YARP) para enrutar peticiones.
- Sincronización de datos eventual con eventos distribuidos.
- **Modular Monoliths**: estructura intermedia entre monolito y microservicio; permite escalar de forma controlada.
- **Patrones de diseño comunes**
- **Dependency Injection** (DI): estándar en .NET Core mediante `IServiceCollection`.
- **Factory**, **Strategy**, **Observer**, **Decorator**, **Mediator**: patrones que se implementan fácilmente con C# gracias a delegates, interfaces y eventos.
- **Command Pattern** para desacoplar acciones de UI en [MAUI NET](/desarrollo%20multiplataforma/maui-net/) o [xamarin](/desarrollo%20multiplataforma/xamarin/).
## Ecosistema moderno de desarrollo .NET
- **Rendimiento y runtime**
- **.NET 9 y AOT (Ahead-of-Time Compilation)**: permite generar binarios nativos más rápidos y ligeros.
- **Span\<T\> y Memory\<T\>**: optimización de acceso a memoria.
- **Minimal APIs** en [ASP NET](/backend/asp-net/) para servicios ligeros.
- **NativeAOT** para entornos sin runtime preinstalado.
- **Interoperabilidad multiplataforma**
- [MAUI NET](/desarrollo%20multiplataforma/maui-net/) para apps móviles, escritorio y web híbrido.
- Blazor y WebAssembly: ejecutar C# en el navegador sin JavaScript.
- Integración con android mediante bindings nativos o APIs de plataforma.
- Comunicación entre [cpp](/software%20engineering/cpp/) y .NET vía P/Invoke o C++/CLI.
- **Integración con contenedores y nube**
- [Docker](/software%20engineering/docker/) como entorno de ejecución portátil.
- Publicación directa en [Azure](/cloud/azure/) con `dotnet publish --os linux --arch x64 /t:PublishContainer`.
- Uso de **Kubernetes** con configuraciones Helm o manifestos YAML.
- Logs centralizados mediante **Serilog** o **Seq**.
## Herramientas de productividad y automatización
- **Builds y DevOps**
- CI CD con GitHub Actions, Azure DevOps o Jenkins.
- Versionado semántico automatizado con `GitVersion`.
- Análisis estático con **SonarQube** o **Roslyn Analyzers**.
- **Testing**
- Unit testing con **xUnit** o **NUnit**.
- Mocking de dependencias con **Moq** o **NSubstitute**.
- **Integration Tests** con `WebApplicationFactory` en ASP.NET Core.
- **Benchmarking** con **BenchmarkDotNet**.
## Integración con hojas de cálculo y documentos
- [visual basic VBA](/software%20engineering/visual-basic-vba/) para automatización nativa.
- **ClosedXML**, **Aspose.Cells**, y **EPPlus** como principales librerías .NET para Excel.
- Generación de reportes corporativos:
- Plantillas Excel dinámicas con placeholders.
- Exportación a PDF combinando Aspose.Cells + Aspose.PDF.
- Automatización de reportes financieros o logs operativos.
### Ejemplo: generación avanzada de reportes con ClosedXML
```csharp
using ClosedXML.Excel;
using System.Data;
public class ReportGenerator
{
public void Generate(DataTable data)
{
using var workbook = new XLWorkbook();
var ws = workbook.Worksheets.Add("Reporte");
// Encabezados
for (int i = 0; i < data.Columns.Count; i++)
ws.Cell(1, i + 1).Value = data.Columns[i].ColumnName;
// Cuerpo
ws.Cell(2, 1).InsertData(data.AsEnumerable());
// Estilo
ws.RangeUsed().Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
ws.Columns().AdjustToContents();
workbook.SaveAs("ReporteAvanzado.xlsx");
}
}
`
Extensiones y ecosistema externo
-
ORMs y acceso a datos
- Entity Framework Core con LINQ-to-SQL y Migrations.
- Dapper para consultas rápidas y control sobre SQL.
- Prisma.NET (alternativa moderna multiplataforma).
-
Autenticación y seguridad
- Identity Server para OAuth2 y OpenID Connect.
- JWT para microservicios.
- Encriptación de datos con
DataProtectionProvider.
-
APIs y mensajería
- gRPC para comunicación binaria eficiente.
- SignalR para tiempo real (chats, dashboards).
- MediatR para CQRS e inyección de comportamientos cross-cutting (logging, validaciones).
Siguientes pasos y temas por expandir
- Event Sourcing y CQRS con .NET
- Saga Pattern y transacciones distribuidas
- Testing distribuido entre microservicios
- Optimización y profiling .NET
- [[Reflexión y metaprogramación en C#]]
- Interoperabilidad avanzada con C++ y Rust desde .NET
- Desarrollo de librerías NuGet internas
- Arquitectura hexagonal aplicada a .NET Core
.NET — Fundamentos complementarios y conceptos esenciales
Fundamentos del ecosistema .NET
1. CLR, BCL y compilación
- CLR (Common Language Runtime)
Es el motor de ejecución de .NET, responsable de:- Gestión de memoria (GC, heap, stack).
- Seguridad y aislamiento de código (sandboxing, CAS).
- Ejecución de código intermedio (IL) compilado a máquina nativa mediante JIT o AOT.
- BCL (Base Class Library)
Conjunto de namespaces fundamentales como:System,System.IO,System.Collections,System.Threading,System.Net.- Proporciona estructuras base, colecciones, IO, red, threading, tareas y utilidades generales.
- Facilita la interoperabilidad entre lenguajes soportados (C#, F#, VB.NET).
- Compilación y despliegue
- JIT (Just-in-Time): compila el código IL en tiempo de ejecución.
- AOT (Ahead-of-Time): genera binarios nativos optimizados (ideal para entornos embebidos o contenedores).
- Assembly (
.dllo.exe): unidad de despliegue que incluye metadatos, IL y recursos. - NuGet: sistema de gestión de dependencias y distribución de paquetes.
2. Tipos, memoria y gestión
- Tipos por valor y por referencia
- Valor:
struct,enum→ almacenados en stack. - Referencia:
class,interface,delegate,array→ heap.
- Valor:
- Garbage Collector (GC)
- Administra la memoria automáticamente.
- Generacional (Gen 0, 1, 2) para optimizar rendimiento.
- Permite modos configurables (
Server,Workstation,SustainedLowLatency).
- Span<T> y Memory<T>
- Acceso seguro y eficiente a datos sin copias adicionales.
- Fundamentales en .NET moderno para optimización de rendimiento.
3. Asincronía y concurrencia
- Task-based Asynchronous Pattern (TAP)
Usaasync/awaitpara manejar I/O no bloqueante.Task.Run()→ ejecución paralela en pool de threads.ValueTask→ reduce overhead en operaciones rápidas o sincrónicas.
- Parallelism & Threading
Parallel.ForyParallel.ForEachpara procesamiento concurrente.System.Threading.Channelspara pipelines asincrónicos.PLINQpara consultas paralelas sobre colecciones.
4. Configuración, logging y dependencia
- Configuración flexible
appsettings.json, variables de entorno, secrets locales.IConfigurationyIOptions<T>para inyección tipada.
- Logging unificado
ILogger<T>integrado en todo el ecosistema.- Integraciones con Serilog, Seq, Application Insights.
- Dependency Injection nativo
- Registro mediante
AddTransient,AddScoped,AddSingleton. - Compatible con
IServiceProvidery decoradores dinámicos.
- Registro mediante
Fundamentos de desarrollo y despliegue
5. Entrada/salida y red
- System.IO
- Streams, archivos, directorios y buffers.
- Asincronía con
FileStreamyStreamReaderasync.
- Networking
HttpClientmoderno,Socketspara bajo nivel.System.Net.Http.Jsonpara APIs REST.- gRPC para comunicación binaria optimizada entre microservicios.
6. Serialización y formatos
- JSON
System.Text.Jsonpor defecto: rápido, eficiente y tipado.Newtonsoft.Jsonaún útil para escenarios complejos (polimorfismo, LINQ a JSON).
- XML y BSON
System.Xmlpara configuraciones o compatibilidad legacy.MongoDB.Bsonpara NoSQL.
- Binary serialization
- Usada en entornos controlados o para performance crítico.
- Reemplazada en la mayoría de casos por JSON o MessagePack.
7. Entornos de ejecución y compatibilidad
- .NET Standard
- Abstracción que unificó APIs entre .NET Framework, .NET Core y Xamarin.
- .NET Core → .NET 5+
- Unificación completa del runtime.
- Soporte multiplataforma real (Windows, Linux, macOS, ARM).
- Frameworks especializados
8. Seguridad y autenticación
- Criptografía
System.Security.Cryptographyincluye AES, RSA, HMAC.- Soporte para certificados X.509 y firma digital.
- Identity y autenticación
- ASP NET Identity para manejo de usuarios y roles.
- JWT para APIs y microservicios.
- OpenID Connect y OAuth2 con Identity Server o Azure AD.
9. Ecosistema de herramientas y flujo de trabajo
CLI y automatización
dotnet new,build,run,publish,test,pack.- Integración con CI/CD y Docker.
- Scripts cross-platform (
.NET toolsglobales y locales).
IDEs y editores
- Visual Studio: entorno completo, debugger avanzado.
- VS Code: ligero y multiplataforma.
- JetBrains Rider: integración profunda con herramientas de análisis.
Testing
- Unit Tests: xUnit, NUnit, MSTest.
- Mocking: Moq, NSubstitute, FakeItEasy.
- Integración y E2E: Playwright.NET, Selenium, WebApplicationFactory.
- Coverage y pipelines: integración con Azure DevOps o GitHub Actions.
10. Ecosistema moderno y comunidad
- NuGet y GitHub Packages para distribución de librerías.
- Open Source en .NET: .NET runtime, Roslyn, ASP.NET Core, EF Core.
- Comunidad activa: .NET Foundation, Microsoft Learn, Stack Overflow.
- Actualizaciones frecuentes: releases semestrales con .NET 9 y versiones LTS (cada 2 años).
Siguientes expansiones recomendadas
- Internals del CLR y JIT avanzado
- Memoria, GC y optimización de heap
- Patrones asincrónicos y concurrencia avanzada
- Networking de alto rendimiento en .NET
- Metaprogramación con Reflection y Source Generators
- Creación de NuGet packages internos y versionado semántico
- Desarrollo multiplataforma con MAUI y Blazor Hybrid
- Infraestructura como código con .NET y Terraform
.NET — Temas avanzados y áreas complementarias
1. Internals del CLR y optimización avanzada
Ejecución interna del CLR
- Metadata y Reflection
- Cada
Assemblycontiene metadata tables que describen tipos, métodos y atributos. System.Reflectionpermite inspección y creación dinámica de tipos en runtime.- Reflection.Emit y DynamicMethod permiten generar IL dinámico (útil en frameworks o proxies).
- Cada
- Runtime Generics
- Generics se implementan mediante reification completa: los tipos genéricos existen en tiempo de ejecución.
- Permite reflejar, instanciar y optimizar tipos genéricos con constraints (
where T : class, etc.). - Reduce boxing/unboxing en colecciones tipadas (
List<int>vsArrayList).
- Tiered Compilation
- El CLR usa dos fases: compilación rápida y optimización progresiva.
- Tier 0: código JIT rápido para inicio veloz.
Tier 1: optimización posterior basada en perfilado (Hot Path JIT).
- Profile-guided Optimization (PGO)
- A partir de .NET 8, el runtime ajusta optimizaciones según ejecución real.
- Permite mejoras automáticas de rendimiento en builds posteriores.
2. Memoria, GC y optimización del heap
- Estructura de memoria
- Stack: variables locales y llamadas.
- Heap: objetos, closures, referencias.
- LOH (Large Object Heap): bloques >85KB, liberados en GC completo.
- Pinned Objects: evitan movimiento de memoria (útiles en interoperabilidad).
- Técnicas de optimización
- Evitar allocations innecesarias (usar
Span,ArrayPool). - Reutilizar buffers (patrón Object Pooling con
Microsoft.Extensions.ObjectPool). - Aplicar structs inmutables y readonly cuando sea posible.
- Usar ValueTask y IAsyncEnumerable para reducir overhead asincrónico.
- Evitar allocations innecesarias (usar
3. Concurrencia avanzada
- Dataflow y actores
System.Threading.Tasks.Dataflow: modelo de bloques (producer-consumer, pipelines).- Implementación de patrones actor-like para procesamiento concurrente sin locks.
- Async Streams
await foreachenIAsyncEnumerable<T>permite flujos asincrónicos continuos.
- Synchronization Context
4. Networking de alto rendimiento
- Sockets y pipelines
System.IO.Pipelines: base interna de Kestrel y SignalR, optimiza I/O sin copias.SocketAsyncEventArgspara operaciones masivas de red sin crear objetos.
- HTTP/3 y QUIC
- Soporte en .NET 8+ para HTTP/3 (más rápido, seguro y basado en UDP).
- MessagePack y gRPC
- MessagePack: serialización binaria ultrarrápida.
- gRPC: comunicación tipo RPC con contratos
.proto, ideal para microservicios.
5. Metaprogramación y generación de código
- Reflection y atributos
- Atributos personalizados para metadata declarativa (
[Authorize],[CustomMapping]). - Inspección y ejecución dinámica según decoradores.
- Atributos personalizados para metadata declarativa (
- Source Generators
- Ejecutan en compilación para generar código estático.
- Usados en frameworks modernos (por ejemplo,
System.Text.Jsongenera serializadores a compile-time). - Mejora rendimiento evitando reflection runtime.
- Roslyn APIs
- Permiten análisis y transformación de código fuente (linting, refactoring, tooling interno).
6. Extensibilidad e interoperabilidad
- Interop con C++
DllImportyexternpara llamar funciones nativas (P/Invoke).- C++/CLI para integración profunda y gestión mixta.
- Interop con Rust
- Comunicación vía FFI (
extern "C") usandounsafeyMarshal.
- Comunicación vía FFI (
- COM Interop
- Uso de librerías legacy (Office, Windows Shell) desde .NET moderno.
- Embeddings
- .NET embebido dentro de motores C++ o Python con
hostfxrynethost.
- .NET embebido dentro de motores C++ o Python con
7. Infraestructura y despliegue
- Infraestructura como código (IaC)
- Integración con Terraform, Pulumi o Bicep mediante SDKs .NET.
- Observabilidad
- Logging estructurado (Serilog), métricas (Prometheus .NET exporters), tracing (OpenTelemetry).
- Diagnóstico
dotnet-counters,dotnet-trace,dotnet-dumppara profiling live.- PerfView para inspeccionar GC, CPU y memoria.
- Hot Reload
- Permite edición en tiempo real sin recompilar completamente (productividad alta en UI y API).
8. Multiplataforma y dispositivos
- MAUI avanzado
- Integración nativa con sensores, Bluetooth, cámara y almacenamiento.
- Soporte para Blazor Hybrid: web + nativo en una misma app.
- WebAssembly y Blazor WASM
- Ejecución directa en navegador, sin servidor.
- Integración con APIs JS mediante
IJSRuntime.
- IoT y .NET nanoFramework
- Framework liviano para microcontroladores (.NET CLR reducido).
- Uso de
System.Device.Gpiopara hardware Raspberry Pi, ESP32, etc.
9. Cloud-native y resiliencia
- Resiliencia
- Políticas de reintento, fallback y circuit breaker con Polly.
- Integración de resiliencia automática en
HttpClientFactory.
- Distribución y mensajería
- RabbitMQ, Azure Service Bus, Kafka mediante librerías oficiales.
- Event-driven architecture con
MassTransit,RebusoNServiceBus.
- Serverless
- Azure Functions o AWS Lambda con runtime .NET nativo.
- Ejecución basada en eventos y despliegue inmediato desde CLI.
10. Prácticas de ingeniería y calidad
- Versionado y mantenimiento
- LTS (Long Term Support) y Current releases: planificar migraciones.
- Semantic Versioning (SemVer) aplicado a NuGet.
- Performance Testing
BenchmarkDotNetpara microbenchmarks reproducibles.
- Code Quality
- Análisis estático con Roslyn Analyzers.
- Uso de convenciones
StyleCop,FxCop,.editorconfig.
- Documentación
docfxoSandcastlepara generar documentación a partir de XML docs.
11. Integración con otros lenguajes y ecosistemas
- Python y R
- Comunicación vía REST, gRPC o con
Python.NET.
- Comunicación vía REST, gRPC o con
- JavaScript
- Interoperabilidad directa en Blazor WASM o mediante SignalR.
- Java
- Uso de
IKVM.NET(histórico) o integración por API Gateway.
- Uso de
- SQL y NoSQL
- Conectores nativos para SQL Server, PostgreSQL, MongoDB, Redis, Cassandra.
- LINQ-to-Entities y LINQ-to-Objects para consultas tipadas.
12. Pruebas distribuidas y sistemas complejos
- Tests de integración entre microservicios
- Contenedores de prueba con
Testcontainers.NET. - Mock de colas y buses de mensajes.
- Contenedores de prueba con
- Contratos y validación
- Pact Testing (Consumer-Driven Contracts).
- Validaciones automáticas con
FluentValidationyDataAnnotations.
Siguientes pasos y notas relacionadas
- Patrones Enterprise en .NET
- Event Driven Architecture con MassTransit
- Source Generators y metaprogramación práctica
- Profiling y optimización .NET con PerfView y BenchmarkDotNet
- Desarrollo híbrido con MAUI + Blazor
- Implementación de resiliencia avanzada con Polly y HttpClientFactory
- Creación de SDKs y librerías NuGet internas
- Diagnóstico de memoria y GC tuning en producción
.NET — Extensión completa de temas especializados
1. Ecosistema empresarial y arquitectura organizacional
Arquitectura orientada a dominios amplios (DDD + Enterprise)
- Bounded Contexts: cada módulo del negocio tiene su propio modelo y lógica interna, comunicándose mediante eventos o APIs.
- Anti-Corruption Layer (ACL): capa intermedia que evita acoplar dominios heterogéneos.
- Domain Events y Event Bus: coordinación asíncrona entre módulos o microservicios.
- Specification Pattern: encapsula consultas de negocio complejas reutilizables (ideal para Entity Framework Core).
Monitoreo de ecosistemas distribuidos
- Telemetría unificada con OpenTelemetry:
- Tracing: seguimiento de peticiones a través de microservicios.
- Metrics: consumo de CPU, memoria, latencia, throughput.
- Logs correlacionados con
Activity.CurrentyILogger.
Estrategias de migración empresarial
- Migrar desde NET Framework a .NET moderno:
- Análisis con
try-convertoUpgrade Assistant. - Uso de Compatibility Shim Packages.
- Modularización progresiva y despliegue híbrido (.NET Core + Framework coexistentes).
- Análisis con
2. Data Engineering y procesamiento masivo
Acceso y persistencia avanzada
- EF Core avanzado
- Soporte para
Temporal Tables(auditoría histórica). Raw SQLyInterpolated Queriesseguras.Value Converterspara tipos personalizados (ej.Currency,Email).
- Soporte para
- ORM alternativos
- Dapper para queries manuales de alto rendimiento.
Linq2DbyRepoDBpara acceso directo con LINQ optimizado.
- Caching
IMemoryCache,DistributedCache, y Redis conStackExchange.Redis.- Patrón Cache Aside para mejorar tiempos de respuesta.
Data Processing
- Parallel Data Pipelines
- Uso de
Channels,TPL DataflowoIAsyncEnumerablepara ETL interno.
- Uso de
- Integración con sistemas de Big Data
- Conectores hacia Kafka, Spark, o Data Lake con SDKs .NET.
- Batch y scheduling
- Hangfire para tareas programadas persistentes.
- Quartz.NET para orquestación temporal distribuida.
3. DevOps, observabilidad y despliegue continuo
CI/CD avanzado
- Build Pipelines
- GitHub Actions, Azure DevOps, GitLab CI.
- Estrategia de versiones automáticas (tags, commits, branches).
- Deployment Targets
- Docker registries, Azure Web Apps, AWS ECS/Fargate, Kubernetes.
- Publicación multi-stage con YAML pipelines.
- Infraestructura reproducible
- Terraform + .NET SDK.
Pulumicon C# o F# para declarar infraestructura como código.
Observabilidad extendida
- Tracing distribuido
- Correlación de peticiones con
ActivitySource. - Visualización en Jaeger, Zipkin o Application Insights.
- Correlación de peticiones con
- Alertas y dashboards
- Métricas exportadas con Prometheus .NET SDK.
- Integración con Grafana para observación centralizada.
4. Seguridad avanzada
Autenticación y autorización
- Claims-based Authentication con
ClaimsPrincipalyClaimsIdentity. - Role-based Access Control (RBAC) nativo en ASP NET.
- Policies y Requirements para reglas complejas.
- IdentityServer + Duende para OAuth2/OpenID Connect completo.
Cifrado, firma y secretos
- Protección de datos
DataProtectionProviderintegrado en ASP.NET.- Rotación automática de claves.
- Certificados y firma
- Creación de X509 con
System.Security.Cryptography.X509Certificates. - Validación de firma y timestamp en documentos.
- Creación de X509 con
- Secrets y credenciales
dotnet user-secretsen desarrollo.- Azure Key Vault o AWS Secrets Manager en producción.
5. Testing distribuido, QA y performance
Estrategias de pruebas
- Pruebas de carga y estrés
NBomber,k6, oJMetercon endpoints .NET.
- Testcontainers.NET
- Ejecución de bases de datos y colas en contenedores efímeros para integración realista.
- Pact Testing
- Contratos Consumer-Driven entre servicios REST/gRPC.
- Mutation Testing
Stryker.NETpara asegurar cobertura de lógica.
Benchmarking
BenchmarkDotNetpara microbenchmarking.dotnet-traceyPerfViewpara profiling detallado.EventPipepara análisis de eventos runtime (GC, CPU, ThreadPool).
6. Cloud-native y Serverless
Microservicios escalables
- Despliegue en Kubernetes:
- Autoescalado horizontal con
HPA. - ConfigMaps y Secrets para configuración segura.
- Autoescalado horizontal con
- Service Mesh (Istio, Linkerd):
- Tráfico seguro, métricas y resiliencia a nivel red.
- Event-driven con CloudEvents:
- Integración nativa en Azure Event Grid o AWS EventBridge.
Serverless
- Azure Functions / AWS Lambda con .NET
- Cold start reducido con .NET AOT.
- Integración con colas, triggers y timers.
- Durable Functions
- Workflow as code (sagas y orquestaciones distribuidas).
7. Inteligencia artificial, análisis y automatización
IA con .NET
- ML.NET
- Entrenamiento y consumo de modelos ML sin depender de Python.
- Clasificación, regresión, detección de anomalías, recomendadores.
- ONNX Runtime
- Ejecución de modelos preentrenados (PyTorch, TensorFlow) en .NET.
- Integración con OpenAI, Hugging Face
- Consumo de APIs de IA desde .NET con clientes HTTP o SDKs oficiales.
- AI + Office Automation
- Generación automática de reportes Excel o Word integrando ML.NET + ClosedXML o Aspose.Cells for .NET.
8. Frontend y UX en el ecosistema .NET
Blazor
- Blazor Server: renderizado en servidor vía SignalR.
- Blazor WASM: ejecución completa en navegador con WebAssembly.
- Blazor Hybrid (MAUI): UI combinada web + nativa.
- Componentización avanzada
- Reutilización entre proyectos.
- Comunicación por
EventCallbackyCascadingParameter.
Integración con frameworks externos
- Angular, React, Vue
- API REST + JWT gestionado desde ASP NET.
- SSR híbrido (Angular Universal o React Static con .NET backend).
- Interoperabilidad JS
IJSRuntimeyJSObjectReferenceen Blazor.
9. Ecosistema extendido
Lenguajes soportados
- C#
- Lenguaje principal, multiparadigma (OO, FP, asincronía nativa).
- F#
- Funcional puro, ideal para pipelines, data y testing.
- VB.NET
- Mantenido para soporte legacy y entornos administrativos.
- PowerShell
- Automatización avanzada y scripting con .NET Core Runtime.
- C++/CLI
- Interoperabilidad directa con código nativo.
Frameworks especializados
- Orleans
- Modelo actor distribuido para sistemas reactivos y escalables.
- Akka.NET
- Implementación de actores para concurrencia segura y resiliente.
- MassTransit / Rebus
- Mensajería distribuida con sagas, retries, y middleware integrable.
- GraphQL for .NET
- API declarativas con resolvers y esquemas tipados.
10. Ecosistema de productividad y automatización
Generación de documentación
docfxpara portales técnicos.Swashbuckle(Swagger/OpenAPI) para endpoints.NSwagpara generar clientes TypeScript o C# desde APIs.
Herramientas de mantenimiento
- dotnet-format para estilo y convención.
- Roslyn analyzers y StyleCop para inspección automática.
- Dependabot o Renovate para actualizar dependencias.
Automatización interna
- Code Generators y Templates
dotnet new --installpara scaffolding personalizado.- Integración con
T4y Source Generators para boilerplate.
- Builds reproducibles
- MSBuild y YAML pipelines con versiones fijadas.
- Caché de dependencias y artefactos con
nuget.config.
11. Temas para expansión futura
- IA generativa e integración con ML.NET y ONNX
- Arquitecturas distribuidas orientadas a eventos
- Interoperabilidad avanzada con Rust y WebAssembly
- Automatización y scripting con PowerShell y .NET CLI
- Diseño de SDKs empresariales y clientes gRPC internos
- Estrategias de resiliencia y escalado dinámico en Kubernetes
- Sistemas actor con Orleans y Akka.NET
- Integración avanzada de .NET con Big Data y Spark
- Ejecución AOT y compilación cruzada para IoT y edge computing
🧠 .NET Programming CheatSheet
⚙️ Comandos básicos CLI
# Crear proyecto
dotnet new console -n MiApp
dotnet new webapi -n MiApi
dotnet new maui -n MiAppMaui
# Ejecutar y compilar
dotnet run
dotnet build
dotnet watch run
# Gestionar dependencias
dotnet add package Newtonsoft.Json
dotnet restore
# Testing
dotnet test
# Publicar (para Docker o servidor)
dotnet publish -c Release -r linux-x64
`
🧩 Estructura típica de un proyecto .NET
/MiProyecto
/Controllers
/Models
/Services
/Data
wwwroot/
appsettings.json
Program.cs
🧱 Sintaxis esencial C#
// Variables y tipos
int edad = 30;
string nombre = "Edu";
bool activo = true;
// Condicionales
if (edad > 18) Console.WriteLine("Adulto");
else Console.WriteLine("Menor");
// Bucles
for (int i = 0; i < 10; i++) Console.WriteLine(i);
foreach (var item in lista) Console.WriteLine(item);
// Métodos
int Sumar(int a, int b) => a + b;
// Clases y objetos
public class Persona
{
public string Nombre { get; set; }
public void Saludar() => Console.WriteLine($"Hola, soy {Nombre}");
}
🧠 Funcional y LINQ
var numeros = new List<int> {1,2,3,4,5};
var pares = numeros.Where(n => n % 2 == 0)
.Select(n => n * 10)
.ToList();
int suma = numeros.Aggregate((a,b) => a + b);
🗂️ Archivos y JSON
using System.IO;
using System.Text.Json;
var texto = File.ReadAllText("data.txt");
var objeto = JsonSerializer.Deserialize<MiClase>(texto);
File.WriteAllText("salida.json", JsonSerializer.Serialize(objeto));
💉 Dependency Injection
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IUserService, UserService>();
var app = builder.Build();
app.MapGet("/users", (IUserService service) => service.GetAll());
app.Run();
🌐 Minimal API
var app = WebApplication.Create();
app.MapGet("/", () => "Hello .NET!");
app.MapPost("/echo", (string msg) => $"Echo: {msg}");
app.Run();
🧱 Entity Framework Core
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
}
public class User { public int Id { get; set; } public string Name { get; set; } }
Migraciones y base de datos
dotnet ef migrations add Init
dotnet ef database update
Consulta básica
using var db = new AppDbContext();
var users = db.Users.Where(u => u.Name.Contains("Ana")).ToList();
🧰 Testing con xUnit
public class CalculatorTests
{
[Fact]
public void Add_ReturnsCorrectSum()
{
Assert.Equal(4, new Calculator().Add(2,2));
}
}
⚡ Asincronía y tareas
async Task DescargarAsync()
{
var http = new HttpClient();
var data = await http.GetStringAsync("https://api.example.com");
Console.WriteLine(data);
}
🔄 Manejo de errores
try
{
var result = 10 / 0;
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Finalizado");
}
🐳 Docker + .NET
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "MiApp.dll"]
docker build -t miappnet .
docker run -p 8080:80 miappnet
🔐 Autenticación básica con JWT
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidIssuer = "miapp",
ValidateAudience = false,
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("clave-secreta-super-segura"))
};
});
🧾 Logging y configuración
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
var config = builder.Configuration;
string conn = config.GetConnectionString("DefaultConnection");
📦 Serialización y utilidades
var json = JsonSerializer.Serialize(objeto, new JsonSerializerOptions { WriteIndented = true });
var anon = new { Id = 1, Nombre = "Edu" };
🧭 Recursos útiles
- ASP NET
- MAUI NET
- xamarin
- Docker
- Entity Framework Core
- Csharp
- visual basic VBA
- ClosedXML
- Sistemas
- Clean Architecture
- CQRS y Event Sourcing con .NET
- Saga Pattern y transacciones distribuidas
🧠 .NET Programming CheatSheet II — Avanzado
🧩 Arquitectura avanzada
- Clean Architecture (ampliado)
- Capas principales:
- Domain: entidades, value objects, eventos de dominio.
- Application: lógica de negocio, casos de uso, servicios.
- Infrastructure: acceso a datos, servicios externos.
- Presentation: API, UI o endpoints.
- Reglas: las dependencias siempre apuntan hacia el dominio.
- Capas principales:
- CQRS y MediatR
- Separación de comandos y consultas.
IRequest<T>yIRequestHandler<TRequest, TResponse>.- Ideal con
MediatRpara inyección automática de handlers.
public record GetUsersQuery() : IRequest<IEnumerable<User>>;
public class GetUsersHandler : IRequestHandler<GetUsersQuery, IEnumerable<User>>
{
private readonly AppDbContext _db;
public GetUsersHandler(AppDbContext db) => _db = db;
public async Task<IEnumerable<User>> Handle(GetUsersQuery request, CancellationToken ct)
=> await _db.Users.ToListAsync(ct);
}
`
🪶 Reflection y metaprogramación
var type = typeof(User);
foreach (var prop in type.GetProperties())
Console.WriteLine($"{prop.Name} : {prop.PropertyType}");
-
Use cases:
- Serialización personalizada.
- Mapping dinámico entre DTOs.
- Creación de plug-ins y carga de ensamblados en tiempo de ejecución (
Assembly.LoadFrom()).
🧵 Programación concurrente
Parallel.For(0, 10, i => Console.WriteLine(i));
await Task.WhenAll(
DownloadAsync("a"),
DownloadAsync("b")
);
- TPL (Task Parallel Library) para paralelismo de alto nivel.
- Concurrent collections:
ConcurrentDictionary,BlockingCollection. - Channels para pipelines y colas internas (
System.Threading.Channels).
🌐 gRPC y comunicación entre servicios
- gRPC: protocolo binario de alta eficiencia entre microservicios.
- Definir
.proto:
service UserService {
rpc GetUser (UserRequest) returns (UserReply);
}
- Generar código con
Grpc.Tools. - Ideal para comunicación entre servicios .NET o entre lenguajes.
🕸️ SignalR — comunicación en tiempo real
app.MapHub<ChatHub>("/chat");
- Permite comunicación bidireccional en webs y apps MAUI.
- Escenarios: chats, dashboards, actualizaciones en vivo.
- Compatible con WebSockets, SSE y Long Polling.
📡 Integración con APIs externas
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer token");
var data = await client.GetFromJsonAsync<Usuario>("https://api.miapp.com/users/1");
- Typed Clients: inyección nativa en DI.
- Polly: políticas de resiliencia (reintentos, circuit breakers).
🧰 Logging avanzado
-
Serilog
- En
Program.cs:
- En
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
- Enriquecedores para incluir contexto (usuario, requestId).
- Seq o Grafana Loki para visualizar logs distribuidos.
🧮 Background Services y Hosted Workers
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
Console.WriteLine("Running task...");
await Task.Delay(1000, ct);
}
}
}
- Ideal para tareas programadas o listeners de colas.
- Regístralos con
builder.Services.AddHostedService<Worker>();.
💾 Caching y rendimiento
- IMemoryCache para caché en memoria local.
- DistributedCache con Redis.
builder.Services.AddStackExchangeRedisCache(options =>
options.Configuration = "localhost:6379");
- Uso de
OutputCacheen endpoints para optimización de respuestas. - Profiling con
dotnet-trace,dotnet-counters,PerfView.
🧱 Integración con bases de datos NoSQL
- MongoDB
var client = new MongoClient("mongodb://localhost:27017");
var db = client.GetDatabase("test");
var users = db.GetCollection<User>("Users");
await users.InsertOneAsync(new User { Name = "Ana" });
- CosmosDB (Azure) con SDK oficial.
- LiteDB para persistencia embebida en aplicaciones locales.
🔐 Seguridad avanzada
- Data Protection API
var provider = DataProtectionProvider.Create("MiApp");
var protector = provider.CreateProtector("Credenciales");
var encriptado = protector.Protect("clave");
-
Autorización basada en políticas
[Authorize(Policy = "AdminOnly")]builder.Services.AddAuthorization(o => o.AddPolicy("AdminOnly", p => p.RequireRole("Admin")));
-
Rate Limiting Middleware
builder.Services.AddRateLimiter(_ => _.AddFixedWindowLimiter("default",
options => { options.PermitLimit = 5; options.Window = TimeSpan.FromSeconds(10); }));
🧩 Modularidad y plugins dinámicos
- Cargar ensamblados externos:
var asm = Assembly.LoadFrom("MiPlugin.dll");
var type = asm.GetType("MiPlugin.Plugin");
dynamic instance = Activator.CreateInstance(type);
instance.Run();
- Útil para aplicaciones extensibles o sistemas de scripts.
⚙️ Interoperabilidad nativa
- C++/CLI y P/Invoke
[DllImport("kernel32.dll")]
static extern bool Beep(int freq, int dur);
- Comunicación con cpp y librerías nativas.
- Rust o Python interoperables mediante procesos externos o bindings.
🧱 Publicación y despliegue
dotnet publish -c Release -r win-x64 --self-contained true
-
Opciones:
--self-contained: incluye el runtime.-p:PublishSingleFile=true: genera un único ejecutable.-p:PublishTrimmed=true: elimina dependencias no usadas.
-
Despliegue en Docker, Azure, AWS Lambda o Kubernetes.
📦 NuGet y distribución
dotnet pack -c Release
dotnet nuget push bin/Release/MiLib.1.0.0.nupkg -k API_KEY -s https://api.nuget.org/v3/index.json
- Crear librerías reutilizables internas.
- Usar
Directory.Build.propspara configuración global.
🧭 Temas adicionales a explorar
- Source Generators en .NET
- Roslyn Analyzers personalizados
- Performance Tuning con Span y Memory
- .NET AOT y Native Compilation
- Dynamic LINQ y Expression Trees
- Testing distribuido y contenedores de prueba
- Integración avanzada con Azure Functions y Service Bus
🚀 Tendencias .NET 2025
🌍 Visión general
El ecosistema .NET en 2025 refleja un salto hacia la eficiencia, la inteligencia y la unificación del desarrollo multiplataforma. Las tendencias actuales combinan rendimiento nativo, IA integrada, seguridad avanzada y desarrollo orientado al edge computing.
Esta guía sintetiza las líneas más relevantes sin repetir notas previas, enfocándose en evolución, herramientas y estrategias para adoptar estas tendencias.
⚙️ 1. Compilación AOT (Ahead-of-Time) y rendimiento extremo
- NativeAOT consolida la tendencia hacia ejecutables nativos sin dependencia del runtime.
- Ideal para microservicios, apps serverless y entornos edge.
- Reduce startup time, consumo de memoria y tamaño del despliegue.
- AOT híbrido combina rendimiento nativo con depuración JIT cuando se necesita.
- Herramientas:
dotnet publish -p:PublishAot=true,dotnet-native. - Se integra con optimizaciones como
TrimMode=linkpara eliminar código no usado.
📎 Ver también: .NET AOT y Native Compilation · Performance Tuning con Span y Memory
💻 2. Desarrollo multiplataforma unificado
- .NET MAUI madura como framework completo para móvil, escritorio y web híbrido.
- Blazor Hybrid permite compartir lógica entre UI y backend sin JavaScript.
- Visual Studio 2025 integra plantillas unificadas que soportan web + MAUI + gRPC.
- Se consolida la tendencia Full-Stack .NET: un solo lenguaje (C#) para todo el ciclo.
📎 Relacionado: MAUI NET · Blazor · xamarin
🧠 3. Integración con IA y Machine Learning
- ML.NET 3.0 amplía soporte para modelos ONNX y PyTorch.
- Nuevas APIs simplifican el uso de IA generativa en .NET (Azure OpenAI, Hugging Face).
- Integración natural con .NET Aspire, el stack para intelligent cloud-native apps.
- Tendencia: “AI-embedded apps”, donde la IA forma parte de la lógica de negocio.
Ejemplo:
var prediction = mlModel.Predict(new InputData { Text = "Consulta del usuario" });
`
📎 Ver también: Integración IA en .NET · Azure Cognitive Services
☁️ 4. Arquitecturas cloud-native y microservicios
-
.NET se orienta aún más al entorno nativo en la nube:
- Integración directa con Kubernetes, Dapr, y Azure Container Apps.
- Soporte AOT en imágenes base de mcr.microsoft.com/dotnet/aspnet:9.0.
-
Patrones dominantes:
- Event-driven architecture.
- Saga Pattern y Outbox Pattern para consistencia distribuida.
-
Se priorizan despliegues ligeros con observabilidad integrada (OpenTelemetry).
📎 Ver: Saga Pattern y transacciones distribuidas · Docker · Kubernetes
🧩 5. Seguridad avanzada y cumplimiento
- Zero Trust y autenticación federada son el nuevo estándar.
-
.NET refuerza seguridad de APIs mediante:
Microsoft.Identity.Webcon Azure AD.- Políticas de autorización personalizables y claims dinámicos.
-
Supply Chain Security:
- Verificación de paquetes con firmas (
dotnet nuget verify). - Escaneo de dependencias (
dotnet list package --vulnerable).
- Verificación de paquetes con firmas (
📎 Referencias: Autenticación y seguridad · Identity Server
🧰 6. Productividad y experiencia del desarrollador (DX)
- Hot Reload mejorado y scaffolding dinámico.
-
C# 13 introduce nuevas construcciones:
- Primary constructors for classes.
- Discriminated unions.
- Collection expressions simplificadas.
- .NET Aspire ofrece entornos locales reproducibles con dashboards y telemetría nativa.
- Mayor integración entre CLI y DevOps:
dotnet new webapi --use-serilog --use-swagger
📎 Relacionado: CI CD · Roslyn Analyzers personalizados
🔋 7. Sostenibilidad y eficiencia operativa
- Prioridad a reducir coste en la nube y huella energética.
- AOT, pooling de conexiones y GC adaptativo reducen consumo.
- Surgen herramientas como GreenOps Analyzer para medir impacto energético.
- KPI emergente: Watts per Request (WPR).
📎 Ver: Optimización y profiling .NET · Performance Tuning con Span y Memory
🧱 8. Edge computing e IoT inteligente
- Expansión de .NET hacia dispositivos y entornos desconectados.
- .NET nanoFramework y .NET for IoT soportan microcontroladores ARM.
- Azure IoT Edge + .NET 9 AOT permite despliegues ligeros y seguros en dispositivos industriales.
- Integración con sensores, actuadores y servicios cloud.
📎 Ver: IoT con .NET · Integración con hardware y serial ports
🎮 9. .NET en nuevos dominios: juegos, XR y simulación
- Integración creciente con motores de juego como Godot 4 C# y Stride Engine.
- Se fomenta el uso de .NET para realidad aumentada (AR/XR) con MAUI + Unity Bridge.
- En simulaciones industriales, .NET se usa junto con Blazor WebGPU y ComputeSharp.
- Extiende el alcance de C# a mundos antes reservados a C++.
📎 Referencias: cpp · ComputeSharp · Shaders en .NET
🔮 10. Nuevos horizontes: metaprogramación, análisis y generación de código
- Source Generators 3.0 permiten generar código de alto rendimiento durante la compilación.
- Roslyn Analyzers evolucionan para aplicar linting dinámico, refactors automáticos y code fixes asistidos por IA.
- Surgen frameworks como DotNetGen para crear SDKs internos basados en plantillas.
📎 Ver: Source Generators en .NET · [[Reflexión y metaprogramación en C#]]
🧭 Conclusión
El .NET de 2025 consolida su madurez empresarial y su expansión a nuevas áreas: inteligencia, rendimiento, sostenibilidad y unificación multiplataforma. Los equipos que adopten estas tendencias lograrán software más rápido, seguro y preparado para el futuro. La clave no está solo en usar .NET, sino en diseñar con visión cloud-native, IA-embedded y sostenibilidad desde el inicio.
📎 Siguientes notas:
- Arquitectura Cloud-Native con .NET
- AOT y rendimiento extremo en microservicios
- IA aplicada en .NET con ML.NET y Cognitive Services
- Zero Trust y seguridad avanzada en ASP.NET Core
- .NET 9 — Cambios de lenguaje y nuevas APIs
🔥🔥🔥 MODULOS PRACTICOS net 9
🧱 Módulo 1 – Entorno Productivo Moderno .NET 9 (2025)
🎯 Objetivo
Configurar un entorno de desarrollo .NET 9 moderno, estable y preparado para proyectos reales, con tooling actualizado, productividad, testing y despliegue.
🧰 Requisitos previos
- 🧩 SDK: .NET 9 SDK
- 🧠 IDE: Visual Studio 2022 / JetBrains Rider / VS Code
- 🐳 Docker Desktop (para contenedores)
- 🔍 Postman o HTTPie (para probar APIs)
- 🧾 Git y GitHub CLI (
gh)
🏗️ Creación de un entorno base
# Crear una carpeta raíz para proyectos .NET
mkdir ~/Projects/dotnet2025
cd ~/Projects/dotnet2025
# Inicializar repositorio
git init
dotnet new globaljson --sdk-version 9.0.100
dotnet --info
`
🧩 Estructura recomendada para proyectos reales
/src
/MyApp.Api
/MyApp.Application
/MyApp.Domain
/MyApp.Infrastructure
/tests
/MyApp.Tests
🧭 Mantén la estructura modular desde el inicio. Evita mezclar controladores, entidades y lógica en un mismo proyecto.
🪄 Crear la base API limpia
dotnet new webapi -n MyApp.Api
cd MyApp.Api
dotnet run
👉 Accede a: https://localhost:5001/swagger
⚙️ Configuración esencial
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.MapControllers();
app.Run();
✅ Mantén este
Program.csminimalista; luego añadiremos capas y DI real.
🧱 Añadir herramientas de productividad
dotnet tool install -g dotnet-ef
dotnet tool install -g dotnet-outdated-tool
dotnet tool install -g dotnet-format
dotnet tool install -g dotnet-watch
Verificación
dotnet ef --version
dotnet format --check
dotnet watch run
🔍 Linter, Analyzer y estilo de código
- Agrega archivo
.editorconfigen la raíz:
[*.cs]
indent_size = 4
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_null_propagation = true:suggestion
- Activa Analyzers:
dotnet new editorconfig
dotnet build -warnaserror
🧩 Configuración de GitHub y CI inicial
gh repo create myapp-dotnet --public
git add .
git commit -m "chore: init .NET 9 project"
git push -u origin main
Ejemplo básico de workflow CI (.github/workflows/build.yml)
name: .NET Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- run: dotnet restore
- run: dotnet build --no-restore
- run: dotnet test --no-build --verbosity normal
🧠 Buenas prácticas iniciales
- Usa nombres de proyectos y namespaces coherentes (ej.
Company.Product.Layer). - Commits semánticos:
feat:,fix:,chore:,test:,refactor:. - Automatiza
dotnet restore,format, ytesten CI antes del merge.
✅ Resultado esperado
✔️ Entorno moderno listo ✔️ Proyecto API ejecutándose en .NET 9 ✔️ GitHub + CI funcional ✔️ Herramientas instaladas para productividad
⚡ Módulo 2 – API REST limpia desde cero (ASP.NET Core 9)
🎯 Objetivo
Construir una API REST limpia, modular y mantenible, aplicando buenas prácticas modernas de .NET 9, con capas separadas, validaciones y un ejemplo funcional completo.
🏗️ Estructura del proyecto
En la raíz de tu workspace:
cd src
dotnet new webapi -n MyApp.Api
dotnet new classlib -n MyApp.Application
dotnet new classlib -n MyApp.Domain
dotnet new classlib -n MyApp.Infrastructure
`
Vincula las referencias:
cd MyApp.Api
dotnet add reference ../MyApp.Application
dotnet add reference ../MyApp.Domain
dotnet add reference ../MyApp.Infrastructure
Estructura:
/src
/MyApp.Api
/Controllers
MyApp.Api.csproj
/MyApp.Application
/Services
/MyApp.Domain
/Entities
/MyApp.Infrastructure
/Data
🧩 Dominio: entidad base y ejemplo
MyApp.Domain/Entities/Product.cs
namespace MyApp.Domain.Entities;
public class Product
{
public Guid Id { get; set; } = Guid.NewGuid();
public required string Name { get; set; }
public decimal Price { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
🧠 Capa de aplicación
MyApp.Application/Services/ProductService.cs
using MyApp.Domain.Entities;
namespace MyApp.Application.Services;
public interface IProductService
{
IEnumerable<Product> GetAll();
Product Add(Product product);
}
public class ProductService : IProductService
{
private readonly List<Product> _products = [];
public IEnumerable<Product> GetAll() => _products;
public Product Add(Product product)
{
_products.Add(product);
return product;
}
}
🌐 API – Controlador principal
MyApp.Api/Controllers/ProductController.cs
using Microsoft.AspNetCore.Mvc;
using MyApp.Application.Services;
using MyApp.Domain.Entities;
namespace MyApp.Api.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
private readonly IProductService _service;
public ProductController(IProductService service)
{
_service = service;
}
[HttpGet]
public IActionResult GetAll() => Ok(_service.GetAll());
[HttpPost]
public IActionResult Create([FromBody] Product product)
{
if (string.IsNullOrWhiteSpace(product.Name) || product.Price <= 0)
return BadRequest("Invalid product data.");
var created = _service.Add(product);
return CreatedAtAction(nameof(GetAll), new { id = created.Id }, created);
}
}
⚙️ Inyección de dependencias
MyApp.Api/Program.cs
using MyApp.Application.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// DI
builder.Services.AddSingleton<IProductService, ProductService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.MapControllers();
app.Run();
🔍 Pruebas rápidas con cURL o HTTPie
# Obtener todos los productos
http GET https://localhost:5001/api/product
# Crear nuevo producto
http POST https://localhost:5001/api/product name="Teclado" price:=49.99
🧪 Añadir primer test (opcional)
tests/MyApp.Tests/ProductServiceTests.cs
using MyApp.Application.Services;
using MyApp.Domain.Entities;
using Xunit;
public class ProductServiceTests
{
[Fact]
public void Add_ShouldReturnProduct()
{
var service = new ProductService();
var product = new Product { Name = "Mouse", Price = 25 };
var result = service.Add(product);
Assert.Equal("Mouse", result.Name);
Assert.True(result.Id != Guid.Empty);
}
}
Ejecuta:
dotnet test
🧱 Buenas prácticas
- Mantén la lógica en la capa Application y el estado persistente (DB) en Infrastructure.
- Usa DTOs o Records para los datos de entrada/salida (los agregaremos en el siguiente módulo).
- No dependas de EF Core aún — usa servicios o repositorios abstractos.
✅ Resultado esperado
✔️ API funcional y modular ✔️ Controlador REST limpio ✔️ Lógica separada por capas ✔️ Inyección de dependencias configurada ✔️ Primer test ejecutable
🗄️ Módulo 3 – Persistencia con EF Core 9 y SQLite
🎯 Objetivo
Integrar Entity Framework Core 9 en la capa Infrastructure, crear una base de datos SQLite, y conectar los servicios del dominio con persistencia real.
🧩 Instalación de paquetes
Desde la raíz del proyecto:
cd src/MyApp.Infrastructure
dotnet add package Microsoft.EntityFrameworkCore --version 9.*
dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 9.*
dotnet add package Microsoft.EntityFrameworkCore.Tools --version 9.*
cd ../MyApp.Api
dotnet add package Microsoft.EntityFrameworkCore.Design --version 9.*
`
🧱 Contexto de datos
MyApp.Infrastructure/Data/AppDbContext.cs
using Microsoft.EntityFrameworkCore;
using MyApp.Domain.Entities;
namespace MyApp.Infrastructure.Data;
public class AppDbContext : DbContext
{
public DbSet<Product> Products => Set<Product>();
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>(entity =>
{
entity.HasKey(p => p.Id);
entity.Property(p => p.Name)
.IsRequired()
.HasMaxLength(100);
entity.Property(p => p.Price)
.HasPrecision(10, 2);
});
}
}
🧠 Configurar EF Core en el API
MyApp.Api/Program.cs
using Microsoft.EntityFrameworkCore;
using MyApp.Infrastructure.Data;
using MyApp.Application.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// EF Core + SQLite
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")));
// DI Services
builder.Services.AddScoped<IProductService, ProductService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.MapControllers();
app.Run();
⚙️ Configuración de conexión
MyApp.Api/appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=../MyApp.Infrastructure/app.db"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning"
}
},
"AllowedHosts": "*"
}
🧩 Adaptar ProductService a persistencia real
MyApp.Application/Services/ProductService.cs
using MyApp.Domain.Entities;
using MyApp.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
namespace MyApp.Application.Services;
public class ProductService : IProductService
{
private readonly AppDbContext _context;
public ProductService(AppDbContext context)
{
_context = context;
}
public IEnumerable<Product> GetAll()
{
return _context.Products.AsNoTracking().ToList();
}
public Product Add(Product product)
{
_context.Products.Add(product);
_context.SaveChanges();
return product;
}
}
🔧 Crear y aplicar migraciones
cd src/MyApp.Api
dotnet ef migrations add InitialCreate --project ../MyApp.Infrastructure --startup-project .
dotnet ef database update
💡 EF Core generará automáticamente app.db en MyApp.Infrastructure/.
🧩 Verificar persistencia
Ejecuta el proyecto:
dotnet run --project src/MyApp.Api
Luego prueba:
# Crear productos
http POST https://localhost:5001/api/product name="Monitor" price:=199.99
http POST https://localhost:5001/api/product name="Mouse" price:=35.00
# Listar productos
http GET https://localhost:5001/api/product
Deberías ver la lista persistida en app.db.
🔍 Visualizar base de datos
Puedes inspeccionar la base de datos SQLite con:
- 🔧 DB Browser for SQLite
- 🧱 VS Code extension: SQLite Viewer
(
Ctrl+Shift+P → SQLite: Open Database)
🧾 Buenas prácticas
- No usar
SaveChanges()dentro de bucles. Usa transacciones si modificas múltiples entidades. - AsNoTracking() para lecturas rápidas.
- Migrations en el proyecto de infraestructura, nunca en la API directamente.
- Context por request (
AddDbContext), no singleton.
🧩 Extensión: métodos asíncronos
Actualiza el servicio a versión async:
public async Task<IEnumerable<Product>> GetAllAsync()
=> await _context.Products.AsNoTracking().ToListAsync();
public async Task<Product> AddAsync(Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
return product;
}
Y cambia los controladores a async Task<IActionResult>.
✅ Resultado esperado
✔️ Base de datos SQLite real ✔️ Persistencia funcional con EF Core 9 ✔️ Migraciones creadas y aplicadas ✔️ Servicio adaptado a DB ✔️ Lectura y escritura verificadas
🧪 Módulo 4 – Testing integral con xUnit y WebApplicationFactory (.NET 9)
🎯 Objetivo
Probar la API completa con peticiones HTTP simuladas, base de datos en memoria y configuración automática del entorno de test.
Aprenderás a crear un entorno reproducible que valida controladores, servicios y configuración de dependencias.
🧰 Dependencias necesarias
Desde la raíz del proyecto:
cd tests
dotnet new xunit -n MyApp.Tests
cd MyApp.Tests
dotnet add reference ../src/MyApp.Api
dotnet add package Microsoft.AspNetCore.Mvc.Testing --version 9.*
dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 9.*
dotnet add package Microsoft.NET.Test.Sdk --version 17.*
dotnet add package coverlet.collector
`
🧩 Estructura de carpetas recomendada
/tests
/MyApp.Tests
/Integration
ProductApiTests.cs
/Unit
ProductServiceTests.cs
🧱 Clase base para tests de integración
tests/MyApp.Tests/Integration/CustomWebApplicationFactory.cs
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MyApp.Infrastructure.Data;
namespace MyApp.Tests.Integration;
public class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// Eliminar configuración de DB real
var descriptor = services.SingleOrDefault(
d => d.ServiceType == typeof(DbContextOptions<AppDbContext>));
if (descriptor != null) services.Remove(descriptor);
// Añadir base de datos en memoria
services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("TestDb"));
});
}
}
🌐 Test de integración real de la API
tests/MyApp.Tests/Integration/ProductApiTests.cs
using System.Net.Http.Json;
using MyApp.Domain.Entities;
using Xunit;
namespace MyApp.Tests.Integration;
public class ProductApiTests : IClassFixture<CustomWebApplicationFactory>
{
private readonly HttpClient _client;
public ProductApiTests(CustomWebApplicationFactory factory)
{
_client = factory.CreateClient();
}
[Fact]
public async Task PostProduct_ShouldCreateAndReturnProduct()
{
var product = new Product { Name = "Laptop", Price = 999.99M };
var response = await _client.PostAsJsonAsync("/api/product", product);
response.EnsureSuccessStatusCode();
var created = await response.Content.ReadFromJsonAsync<Product>();
Assert.NotNull(created);
Assert.Equal("Laptop", created!.Name);
Assert.True(created.Price > 0);
}
[Fact]
public async Task GetAll_ShouldReturnListOfProducts()
{
var response = await _client.GetAsync("/api/product");
response.EnsureSuccessStatusCode();
var products = await response.Content.ReadFromJsonAsync<IEnumerable<Product>>();
Assert.NotNull(products);
}
}
🧠 Ejecución de los tests
dotnet test --logger "console;verbosity=detailed"
Verás algo como:
[xUnit.net 00:00:01.12] MyApp.Tests.Integration.ProductApiTests.PostProduct_ShouldCreateAndReturnProduct [PASS]
[xUnit.net 00:00:01.19] MyApp.Tests.Integration.ProductApiTests.GetAll_ShouldReturnListOfProducts [PASS]
✅ Si ambos pasan, tu API responde correctamente y la configuración de DI funciona como en producción.
🧩 Test unitario adicional (sin WebApplicationFactory)
tests/MyApp.Tests/Unit/ProductServiceTests.cs
using MyApp.Application.Services;
using MyApp.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using MyApp.Infrastructure.Data;
using Xunit;
public class ProductServiceTests
{
[Fact]
public void Add_ShouldStoreInMemoryContext()
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase("TestDb2")
.Options;
using var context = new AppDbContext(options);
var service = new ProductService(context);
var product = new Product { Name = "Mouse", Price = 25 };
service.Add(product);
Assert.Single(context.Products);
}
}
🧾 Consejos de testeo profesional
- Usa bases de datos in-memory o SQLite in-memory para tests rápidos.
- Cada test debe ser independiente (recrear el contexto en cada método).
- Evita mocks innecesarios si puedes testear la integración real.
- Mantén tests de integración y unitarios separados (carpetas distintas).
- Puedes añadir
dotnet test /p:CollectCoverage=truecon coverlet para cobertura.
🧰 Integración en CI/CD
Agrega al workflow de GitHub Actions:
- name: Run tests
run: dotnet test --no-build --verbosity normal
✅ Resultado esperado
✔️ Tests de integración reales con HTTP ✔️ Base de datos en memoria funcional ✔️ Cobertura de servicios y controladores ✔️ CI con ejecución automática de tests
🖥️ Módulo 5 – Frontend + Integración (Blazor, MAUI y Angular Client)
🎯 Objetivo
Conectar la API .NET creada en módulos previos con diferentes frontends modernos:
- Blazor WebAssembly para aplicaciones SPA .NET puras
- .NET MAUI para apps multiplataforma (desktop + móvil)
- Angular como ejemplo de integración con frameworks externos
🧱 Parte 1: Blazor WebAssembly + API REST
📦 Crear proyecto Blazor
dotnet new blazorwasm -n MyApp.BlazorClient --framework net9.0
cd MyApp.BlazorClient
`
🔗 Configurar HttpClient global
Program.cs
using MyApp.BlazorClient;
using MyApp.BlazorClient.Services;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp =>
new HttpClient { BaseAddress = new Uri("https://localhost:5001/") });
builder.Services.AddScoped<ProductApiClient>();
await builder.Build().RunAsync();
💬 Servicio para consumir la API
Services/ProductApiClient.cs
using System.Net.Http.Json;
using MyApp.Shared;
namespace MyApp.BlazorClient.Services;
public class ProductApiClient
{
private readonly HttpClient _http;
public ProductApiClient(HttpClient http) => _http = http;
public async Task<IEnumerable<ProductDto>?> GetAllAsync()
=> await _http.GetFromJsonAsync<IEnumerable<ProductDto>>("api/product");
public async Task<ProductDto?> CreateAsync(ProductDto product)
{
var response = await _http.PostAsJsonAsync("api/product", product);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<ProductDto>();
}
}
🧩 Componente para mostrar productos
Pages/Products.razor
@page "/products"
@inject ProductApiClient Api
<h3>Products</h3>
@if (products == null)
{
<p>Loading...</p>
}
else
{
<ul>
@foreach (var p in products)
{
<li>@p.Name - @p.Price €</li>
}
</ul>
}
@code {
IEnumerable<ProductDto>? products;
protected override async Task OnInitializedAsync()
{
products = await Api.GetAllAsync();
}
}
✅ Ejecuta dotnet run y abre /products → verás los productos cargados desde la API real.
📱 Parte 2: .NET MAUI – App multiplataforma
⚙️ Crear proyecto MAUI
dotnet new maui -n MyApp.Mobile
cd MyApp.Mobile
🔗 Servicio para API
Services/ProductService.cs
using System.Net.Http.Json;
using MyApp.Shared;
namespace MyApp.Mobile.Services;
public class ProductService
{
private readonly HttpClient _http;
public ProductService()
{
_http = new HttpClient
{
BaseAddress = new Uri("https://localhost:5001/")
};
}
public async Task<List<ProductDto>?> GetAllAsync()
=> await _http.GetFromJsonAsync<List<ProductDto>>("api/product");
}
📲 Página principal
MainPage.xaml.cs
using MyApp.Mobile.Services;
namespace MyApp.Mobile;
public partial class MainPage : ContentPage
{
private readonly ProductService _service = new();
public MainPage()
{
InitializeComponent();
LoadProducts();
}
private async void LoadProducts()
{
var products = await _service.GetAllAsync();
ProductList.ItemsSource = products;
}
}
✅ Ejecuta en Android Emulator o Windows → lista real desde API .NET 9.
🌐 Parte 3: Cliente Angular
🧱 Crear cliente Angular
ng new myapp-angular --standalone
cd myapp-angular
npm install axios
🔗 Servicio API
src/app/api.service.ts
import axios from 'axios';
export class ApiService {
private base = 'https://localhost:5001/api/product';
async getAll() {
const res = await axios.get(this.base);
return res.data;
}
async create(product: any) {
const res = await axios.post(this.base, product);
return res.data;
}
}
🧩 Componente simple
src/app/products.component.ts
import { Component, OnInit } from '@angular/core';
import { ApiService } from './api.service';
@Component({
selector: 'app-products',
template: `
<h3>Products</h3>
<ul>
<li *ngFor="let p of products">{{p.name}} - {{p.price}}€</li>
</ul>
`
})
export class ProductsComponent implements OnInit {
products: any[] = [];
api = new ApiService();
async ngOnInit() {
this.products = await this.api.getAll();
}
}
🔐 Autenticación JWT compartida
🛠️ En API (.NET)
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer(options =>
{
options.Authority = "https://localhost:5001";
options.Audience = "myapi";
});
🧱 En Blazor / Angular
Adjuntar el token JWT a cada petición:
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
🧠 Buenas prácticas de integración
- Centraliza URLs en un
AppSettingsoConfigService. - Usa DTOs compartidos entre backend y frontend (
MyApp.Shared). - En Blazor y MAUI, reutiliza servicios y modelos comunes.
- Mantén la autenticación y autorización coherente (Identity o JWT).
- Aísla lógica de red (API Clients) de la UI.
✅ Resultado esperado
✔️ API consumida desde tres clientes reales ✔️ Patrón de comunicación unificado ✔️ Ejemplo funcional Full Stack .NET + Angular ✔️ Base sólida para apps empresariales multiplataforma
⚙️ Módulo 6 – DevOps, CI/CD y despliegue de proyectos .NET (2025)
🎯 Objetivo
Aprender a automatizar el ciclo de vida completo de una aplicación .NET moderna:
- Build y test automatizados
- Creación de contenedores Docker
- Despliegue continuo (CI/CD)
- Publicación en entornos como Azure Web App, AWS, Render o Vercel
🧱 Estructura base del pipeline
Pipeline de ejemplo con:
- GitHub Actions
- Docker multi-stage build
- Despliegue a Azure Web App
🐋 Parte 1: Dockerfile optimizado
Dockerfile
# Etapa 1: Build
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o /app/publish
# Etapa 2: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]
`
🧪 Test local
docker build -t myapp-api .
docker run -p 8080:8080 myapp-api
Accede a: http://localhost:8080/swagger
🔄 Parte 2: GitHub Actions – CI/CD
.github/workflows/dotnet-ci.yml
name: .NET CI/CD Pipeline
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET 9
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore -c Release
- name: Run tests
run: dotnet test --no-build --verbosity normal
- name: Publish artifacts
run: dotnet publish -c Release -o out
- name: Upload build output
uses: actions/upload-artifact@v4
with:
name: published-app
path: out
✅ Resultado: compila, ejecuta tests y guarda artefactos automáticamente.
☁️ Parte 3: Despliegue automático a Azure Web App
Agrega un segundo workflow:
.github/workflows/deploy.yml
name: Deploy to Azure Web App
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Publish app
run: dotnet publish -c Release -o out
- name: Deploy to Azure
uses: azure/webapps-deploy@v3
with:
app-name: "myapp-dotnet9"
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: ./out
🔐 Configurar secretos
En GitHub → Settings > Secrets and variables > Actions
AZURE_WEBAPP_PUBLISH_PROFILE= XML del perfil de publicación de Azure
🧩 Parte 4: Docker + GitHub Container Registry (GHCR)
Publicar imagen Docker automáticamente
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/${{ github.repository_owner }}/myapp:latest
✅ Resultado:
- Imagen se publica en GHCR (https://ghcr.io/tu-usuario/myapp)
- Puede ser usada en Azure, AWS ECS o Kubernetes
🔧 Parte 5: Variables y configuración por entorno
Usa appsettings.{Environment}.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=db;Database=MyApp;User Id=sa;Password=Pass123;"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
En Program.cs:
builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true);
🧠 Buenas prácticas de DevOps
- Mantén CI/CD separado por entorno (
dev,staging,prod). - Usa branch protection rules y pull request checks.
- Monitorea con Application Insights o Grafana + Prometheus.
- Versiona las imágenes Docker (
myapp:v1.0.0). - Integra Infrastructure as Code (IaC) con Bicep, Terraform o Pulumi.
🚀 Resultado esperado
✔️ Pipeline CI/CD funcionando en GitHub Actions ✔️ Despliegue automático a Azure Web App ✔️ Imagen Docker publicada en GHCR ✔️ Configuración adaptable por entorno ✔️ Base sólida para flujos DevOps profesionales
🛡️ Módulo 7 – Seguridad, Observabilidad y Rendimiento en .NET 9+
tags:: #dotnet #security #jwt #oauth2 #identity #observability #logging #metrics #performance #tracing
🎯 Objetivo
Asegurar y supervisar una API .NET moderna mediante:
- Autenticación JWT y OAuth2
- Protección de endpoints con roles
- Logging estructurado con Serilog
- Observabilidad con OpenTelemetry y Grafana
- Optimización de rendimiento y profiling
🔑 Parte 1: Autenticación JWT
🧩 Instalar paquetes
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt
`
⚙️ Configurar autenticación en Program.cs
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var key = Encoding.ASCII.GetBytes("SuperSecretKeyForJwtToken12345!");
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuerSigningKey = true
};
});
🧱 Crear controlador de autenticación
Controllers/AuthController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
[HttpPost("login")]
public IActionResult Login([FromBody] LoginRequest request)
{
if (request.Username != "admin" || request.Password != "1234")
return Unauthorized();
var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("SuperSecretKeyForJwtToken12345!"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.Name, request.Username),
new Claim(ClaimTypes.Role, "Admin")
};
var token = new JwtSecurityToken(
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: creds
);
return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
}
}
public record LoginRequest(string Username, string Password);
🔐 Proteger endpoints
[Authorize(Roles = "Admin")]
[HttpPost]
public IActionResult CreateProduct(Product product)
{
_service.Add(product);
return Ok(product);
}
🔑 Parte 2: OAuth2 con Microsoft Identity Platform
Configuración mínima para aplicaciones empresariales.
📦 Paquetes
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect
⚙️ Configuración en Program.cs
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
🧩 appsettings.json
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "mydomain.onmicrosoft.com",
"TenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"ClientId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
"CallbackPath": "/signin-oidc"
}
✅ Ideal para aplicaciones con Azure AD, B2C o entornos corporativos.
📊 Parte 3: Logging estructurado con Serilog
🧱 Instalar
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
⚙️ Configurar
Program.cs
using Serilog;
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
builder.Host.UseSerilog();
🧩 Ejemplo en controlador
private readonly ILogger<ProductController> _logger;
public ProductController(IProductService service, ILogger<ProductController> logger)
{
_service = service;
_logger = logger;
}
[HttpGet]
public IActionResult GetAll()
{
_logger.LogInformation("Fetching all products at {time}", DateTime.UtcNow);
return Ok(_service.GetAll());
}
🔭 Parte 4: Observabilidad con OpenTelemetry
📦 Instalar
dotnet add package OpenTelemetry.Exporter.Console
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
⚙️ Configurar
Program.cs
using OpenTelemetry.Trace;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
builder.Services.AddOpenTelemetry()
.WithTracing(t => t
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyApp.Api"))
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddOtlpExporter(o => o.Endpoint = new Uri("http://localhost:4317")))
.WithMetrics(m => m
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation()
.AddOtlpExporter());
📈 Exportar datos a Grafana o Jaeger
Ejecuta contenedores con Docker:
docker run -d --name jaeger -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p 16686:16686 jaegertracing/all-in-one:latest
Accede a: http://localhost:16686 → visualiza trazas y spans.
⚡ Parte 5: Optimización de rendimiento
🧩 Diagnóstico en tiempo real
dotnet-counters monitor --process-id <PID>
🧰 Perf tips:
- Usa
async/awaiten IO intensivo - Implementa caching con
IMemoryCacheo Redis - Evita
ToList()prematuros en LINQ - Usa
AddResponseCompression()yUseResponseCaching() - Ajusta
Kestrelpara concurrencia alta:
builder.WebHost.ConfigureKestrel(options =>
{
options.Limits.MaxConcurrentConnections = 1000;
});
🧠 Buenas prácticas
- Mantén claves fuera del código → usa
dotnet user-secretsoAzure Key Vault. - Registra solo lo necesario → usa niveles (
Information,Warning,Error). - Aplica Rate Limiting en endpoints públicos (
AddRateLimiter). - Combina Serilog + OpenTelemetry para trazas unificadas.
- Revisa Memory Dumps con
dotnet-dump analyzeen producción.
✅ Resultado esperado
✔️ Autenticación JWT / OAuth2 funcionando ✔️ Endpoints protegidos con roles ✔️ Logging estructurado y persistente ✔️ Trazabilidad distribuida con OpenTelemetry ✔️ Monitoreo de rendimiento en tiempo real ✔️ API lista para entornos productivos y auditables
🏗️ Módulo 8 – Arquitecturas avanzadas y patrones distribuidos (.NET 9+)
Objetivo práctico
Implementar patrones reales para sistemas distribuidos con .NET 9: Microservicios, CQRS, Event Sourcing, Sagas/Compensations, EventBus (RabbitMQ), gRPC, Outbox pattern, y resiliencia (Polly). Cada bloque incluye ejemplos ejecutables mínimos y comandos para probar localmente.
1. Diseño general de microservicios
- Servicios pequeños con responsabilidad única (User, Order, Payment, Catalog).
- Comunicación:
- Sincrónica: gRPC o HTTP/REST.
- Asincrónica: RabbitMQ / Kafka / Dapr pub/sub.
- Persistencia: base de datos por servicio (DB-per-service).
- Consistencia eventual: Outbox + EventBus o Sagas para flujos transaccionales.
2. CQRS con MediatR (comandos/consultas separados)
2.1 Ejemplo: comando y handler con MediatR
Código: Command y Handler
// Application/Commands/CreateOrderCommand.cs
public record CreateOrderCommand(Guid CustomerId, List<OrderItemDto> Items) : IRequest<Guid>;
// Application/Handlers/CreateOrderHandler.cs
public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, Guid>
{
private readonly AppDbContext _db;
private readonly IPublishEndpoint _publisher; // MassTransit or custom bus
public CreateOrderHandler(AppDbContext db, IPublishEndpoint publisher)
{
_db = db;
_publisher = publisher;
}
public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken ct)
{
var order = new Order { CustomerId = request.CustomerId, Items = request.Items.Select(i => new OrderItem(i.ProductId, i.Quantity)).ToList() };
_db.Orders.Add(order);
await _db.SaveChangesAsync(ct);
// Publicar evento de dominio
await _publisher.Publish(new OrderCreatedEvent(order.Id, order.Total), ct);
return order.Id;
}
}
`
2.2 Registro en DI
// Program.cs
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<CreateOrderCommand>());
3. Event Sourcing (concepto + ejemplo mínimo)
- Almacenar sólo eventos inmutables; reconstruir estado por rehidratación.
- Usar una tabla
EventsconId, AggregateId, Type, Data(json), Version, CreatedAt.
3.1 Ejemplo: evento y apéndice
Código: Event entity y append
// Infrastructure/Events/EventEntity.cs
public class EventEntity
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid AggregateId { get; set; }
public string Type { get; set; } = null!;
public string Data { get; set; } = null!;
public int Version { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
// Usage: append event
var evt = new EventEntity { AggregateId = order.Id, Type = "OrderCreated", Data = JsonSerializer.Serialize(new { order.Id, order.Total }), Version = 1 };
db.Events.Add(evt);
await db.SaveChangesAsync();
4. Outbox pattern (garantizar publicación de eventos)
- Escribir evento en la misma transacción que la entidad (DB), luego enviar los eventos desde la tabla
Outboxmediante un proceso background para asegurar entrega at-least-once.
4.1 Ejemplo: esquema Outbox y worker
Código: Outbox entity
public class OutboxMessage
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Type { get; set; } = null!;
public string Payload { get; set; } = null!;
public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
public bool Sent { get; set; } = false;
}
Código: Worker simple (BackgroundService)
public class OutboxDispatcher : BackgroundService
{
private readonly IServiceScopeFactory _scopes;
private readonly IPublishEndpoint _publisher;
public OutboxDispatcher(IServiceScopeFactory scopes, IPublishEndpoint publisher)
{
_scopes = scopes;
_publisher = publisher;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using var scope = _scopes.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var pending = await db.Set<OutboxMessage>().Where(m => !m.Sent).Take(20).ToListAsync(stoppingToken);
foreach (var msg in pending)
{
await _publisher.Publish(msg, stoppingToken); // map to domain event
msg.Sent = true;
}
await db.SaveChangesAsync(stoppingToken);
await Task.Delay(1000, stoppingToken);
}
}
}
5. EventBus con RabbitMQ (MassTransit ejemplo)
5.1 Docker Compose para RabbitMQ
Código: docker-compose.yml
version: '3.8'
services:
rabbitmq:
image: rabbitmq:3.11-management
ports:
- "5672:5672"
- "15672:15672"
Comando:
docker compose up -d
5.2 Configurar MassTransit en servicios
Código: Program.cs (MassTransit)
builder.Services.AddMassTransit(x =>
{
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host("rabbitmq", "/", h => { /* credenciales si es necesario */ });
cfg.ConfigureEndpoints(context);
});
});
5.3 Consumidor simple
Código: OrderCreatedConsumer
public class OrderCreatedEvent
{
public Guid OrderId { get; init; }
public decimal Total { get; init; }
}
public class OrderCreatedConsumer : IConsumer<OrderCreatedEvent>
{
public Task Consume(ConsumeContext<OrderCreatedEvent> context)
{
Console.WriteLine($"OrderReceived: {context.Message.OrderId} total {context.Message.Total}");
return Task.CompletedTask;
}
}
6. Sagas (orquestación de procesos) con MassTransit
- Usar Sagas para orquestar flujos (Order -> Payment -> Inventory -> Confirmation).
- Persistir estado de saga (EF Core or Mongo) y modelar correcciones (compensaciones).
6.1 Ejemplo: Saga State & Saga
Código: OrderState
public class OrderState : SagaStateMachineInstance
{
public Guid CorrelationId { get; set; }
public string CurrentState { get; set; } = null!;
public Guid OrderId { get; set; }
public bool PaymentConfirmed { get; set; }
}
Código: StateMachine (esqueleto)
public class OrderStateMachine : MassTransitStateMachine<OrderState>
{
public State AwaitingPayment { get; private set; }
public Event<OrderCreatedEvent> OrderCreated { get; private set; }
public OrderStateMachine()
{
InstanceState(x => x.CurrentState);
Event(() => OrderCreated, x => x.CorrelateById(m => m.Message.OrderId));
Initially(
When(OrderCreated)
.Then(context => { context.Instance.OrderId = context.Data.OrderId; })
.TransitionTo(AwaitingPayment)
);
// agregar manejo de pago, compensaciones, timeouts...
}
}
7. gRPC para llamadas síncronas rápidas
7.1 Definir contrato .proto
Código: proto/order.proto
syntax = "proto3";
package orders;
service OrderService {
rpc GetOrder (OrderRequest) returns (OrderReply);
}
message OrderRequest {
string id = 1;
}
message OrderReply {
string id = 1;
double total = 2;
string status = 3;
}
7.2 Agregar gRPC al proyecto (.NET)
// Program.cs
builder.Services.AddGrpc();
app.MapGrpcService<OrderGrpcService>();
7.3 Implementar servicio gRPC
Código: OrderGrpcService.cs
public class OrderGrpcService : OrderService.OrderServiceBase
{
public override Task<OrderReply> GetOrder(OrderRequest request, ServerCallContext context)
{
// obtener desde DB
return Task.FromResult(new OrderReply { Id = request.Id, Total = 100.0, Status = "Created" });
}
}
8. Dapr (alternativa ligera para pub/sub, state, bindings)
- Dapr simplifica pub/sub, state stores y service invocation sin acoplar demasiado.
- Instalar Dapr CLI local y ejecutar
dapr run --app-id orders -- dotnet run.
8.1 Ejemplo: publicar evento con Dapr
Código: Publicar evento (HTTP)
var client = new HttpClient();
await client.PostAsJsonAsync("http://localhost:3500/v1.0/publish/pubsub/order_created", new { orderId = id, total = total });
8.2 Suscriptor en otro servicio
- Configurar endpoint
/dapr/subscribeo usar SDK .NET (Dapr.Client).
9. Resiliencia: Polly (reintentos, circuit breaker, timeout)
9.1 Paquete y política
dotnet add package Polly.Extensions.Http
9.2 Ejemplo: HttpClient con políticas
Código: Program.cs - HttpClientFactory + Polly
builder.Services.AddHttpClient("payment", client => client.BaseAddress = new Uri("https://payment.local"))
.AddTransientHttpErrorPolicy(p => p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(500)))
.AddTransientHttpErrorPolicy(p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
10. Testing de integración distribuida (Testcontainers)
10.1 Usar Testcontainers.NET para RabbitMQ/DB
Código: ejemplo de test setup (C#)
var rabbit = new RabbitMqTestcontainerBuilder().Build();
await rabbit.StartAsync();
// iniciar bus con conexión rabbit.ConnectionString
11. Observabilidad específica de microservicios
- Trazas: OpenTelemetry + Jaeger (OTLP).
- Métricas: Prometheus exporters + Grafana dashboards por servicio.
- Logs: Correlación por
traceIden Serilog/Seq.
12. Despliegue y orquestación recomendada
- Kubernetes con Helm charts.
- Separar infra: RabbitMQ (stateful), DB (managed), app (deployments).
- Rolling updates + readiness/liveness probes.
- Considerar Service Mesh (Istio/Linkerd) para políticas de red y telemetría.
13. Checklist práctico (qué implementar primero)
- Separar responsabilidades en servicios pequeños.
- Implementar CQRS mínimo (commands + queries).
- Añadir Outbox para eventos publicados desde la transacción DB.
- Desplegar RabbitMQ local y validar pub/sub.
- Implementar Sagas para flujos de negocio multistep.
- Añadir gRPC para caminos síncronos de baja latencia.
- Integrar resiliencia con Polly.
- Habilitar OpenTelemetry y dashboards básicos.
- Tests de integración end-to-end con Testcontainers.
Comandos útiles rápidos
# levantar RabbitMQ
docker compose -f docker-compose.yml up -d
# ejecutar migraciones (ej. infra project)
dotnet ef database update --project src/MyService.Infrastructure --startup-project src/MyService.Api
# ejecutar tests con containers
dotnet test tests/MyService.Tests
Notas de implementación
- Empezar simple: CQRS + Outbox + EventBus. Añadir Sagas cuando necesites coordinaciones transaccionales.
- Priorizad idempotencia en consumidores (recibidos múltiples).
- Modelar eventos como contratos estables (versionable).
- Monitorizar entrega (DLQ, retries y dead-letter queues en RabbitMQ).
🚀 Módulo 9 – Rendimiento, Profiling y Publicación Cloud-Ready (.NET 9+)
Objetivo práctico
Optimizar, analizar y desplegar aplicaciones .NET 9 en entornos cloud-ready, midiendo rendimiento con herramientas reales, aplicando patrones de optimización, y preparando el proyecto para Azure, AWS, o Kubernetes con CI/CD y observabilidad.
1. Fundamentos de rendimiento en .NET
Principios clave
- Evitar bloqueos innecesarios → usar
async/awaiten IO-bound. - Reducir asignaciones en bucles críticos (usar
Span<T>,Memory<T>). - Evitar LINQ costoso en loops → preferir bucles explícitos o
ArrayPool<T>. - Configurar correctamente el Garbage Collector (GC):
- Server GC para entornos productivos.
- Sustituir colecciones por versiones especializadas (
ConcurrentQueue,ArrayPool).
Configuración del GC
<!-- app.config o runtimeconfig.json -->
<configuration>
<runtime>
<gcServer enabled="true"/>
<gcConcurrent enabled="true"/>
</runtime>
</configuration>
`
2. Profiling y diagnóstico local
Herramientas recomendadas
- dotnet-counters → métricas en tiempo real.
- dotnet-trace → capturar eventos de rendimiento.
- dotnet-dump → análisis de memoria.
- PerfView o Visual Studio Profiler → profiling detallado.
- JetBrains dotTrace / dotMemory → análisis avanzado.
Ejemplo: métricas en tiempo real
dotnet-counters monitor --process-id <pid> System.Runtime
Ejemplo: grabar un trace
dotnet-trace collect --process-id <pid> --format speedscope
Abre en https://www.speedscope.app para visualizar la llama de CPU.
3. Benchmarking con BenchmarkDotNet
Instalación
dotnet add package BenchmarkDotNet
Ejemplo: benchmark simple
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
public class StringBenchmarks
{
private string[] words = Enumerable.Repeat("benchmark", 1000).ToArray();
[Benchmark]
public string Join() => string.Join(",", words);
[Benchmark]
public string ManualConcat()
{
var sb = new StringBuilder();
foreach (var w in words) sb.Append(w).Append(',');
return sb.ToString();
}
}
BenchmarkRunner.Run<StringBenchmarks>();
Salida típica:
| Method | Mean | Error | StdDev | Allocated |
|------------ |----------:|---------:|---------:|-----------:|
| Join | 12.45 us | 0.11 us | 0.10 us | 12.3 KB |
| ManualConcat| 25.18 us | 0.15 us | 0.14 us | 48.5 KB |
4. Diagnóstico en producción con OpenTelemetry + Logs
Instrumentación básica
builder.Services.AddOpenTelemetry()
.WithMetrics(m => m.AddAspNetCoreInstrumentation().AddRuntimeInstrumentation())
.WithTracing(t => t.AddAspNetCoreInstrumentation().AddHttpClientInstrumentation());
Exportar a herramientas
- Azure Monitor, Grafana, Jaeger o Zipkin.
- Log sinks:
Serilog + SeqoApplication Insights.
Ejemplo: configuración Serilog + Seq
Log.Logger = new LoggerConfiguration()
.WriteTo.Seq("http://localhost:5341")
.Enrich.WithCorrelationId()
.CreateLogger();
5. Optimización de API ASP.NET Core
5.1 Configuración recomendada en Program.cs
builder.WebHost
.UseKestrel(o =>
{
o.AddServerHeader = false;
o.Limits.MaxConcurrentConnections = 1000;
o.Limits.KeepAliveTimeout = TimeSpan.FromSeconds(120);
})
.UseUrls("http://*:5000");
builder.Services.Configure<RouteOptions>(o => o.LowercaseUrls = true);
builder.Services.AddResponseCompression();
builder.Services.AddMemoryCache();
5.2 Minimizar overhead de middleware
- Evitar middlewares innecesarios en rutas críticas.
- Aplicar
[ResponseCache]oETagen endpoints idempotentes. - Usar
IResultminimal APIs para máxima eficiencia.
5.3 Ejemplo de endpoint optimizado
app.MapGet("/status", () => Results.Ok(new { uptime = Environment.TickCount64 }))
.CacheOutput(policy => policy.Expire(TimeSpan.FromSeconds(30)));
6. Load Testing (carga y stress)
Opciones
- k6 → moderno, scriptable (JavaScript).
- Bombardier → CLI sencilla.
- Azure Load Testing → pruebas cloud integradas.
Ejemplo con k6
npm install -g k6
// load.js
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
http.get('http://localhost:5000/api/orders');
sleep(0.1);
}
Ejecutar:
k6 run --vus 50 --duration 30s load.js
7. Contenedores y publicación
Dockerfile productivo optimizado
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Ejecutar y probar
docker build -t myapp:latest .
docker run -p 8080:8080 myapp:latest
8. Despliegue en Azure
Opción 1: Azure App Service
az webapp up --name myapp2025 --resource-group MyRG --runtime "DOTNET:9"
Opción 2: Azure Container Apps (ACA)
az containerapp up \
--name myapp \
--resource-group MyRG \
--environment myenv \
--image myapp:latest \
--ingress external --target-port 8080
Opción 3: Azure Kubernetes Service (AKS)
kubectl create namespace myapp
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
9. Despliegue en AWS
Opción 1: AWS Elastic Beanstalk
eb init -p "dotnet 9" MyApp
eb create myapp-env
Opción 2: AWS ECS con Fargate
aws ecs create-cluster --cluster-name MyCluster
aws ecs register-task-definition --cli-input-json file://ecs-task.json
aws ecs create-service --cluster MyCluster --service-name myapp --task-definition myapp-task
Opción 3: AWS Lambda con .NET
dotnet lambda deploy-serverless MyLambdaApp
10. CI/CD cloud-ready (GitHub Actions ejemplo)
Workflow .github/workflows/build-deploy.yml
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Build
run: dotnet build --configuration Release
- name: Publish
run: dotnet publish -c Release -o output
- name: Deploy to Azure
uses: azure/webapps-deploy@v3
with:
app-name: myapp2025
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: output
11. Monitorización post-despliegue
Azure Application Insights
- Trazas automáticas de peticiones, dependencias y excepciones.
- Consultas Kusto (KQL) para análisis:
requests
| where duration > 200ms
| summarize avg(duration) by operation_Name
AWS CloudWatch
- Logs centralizados, alarmas en latencia o errores.
- Integración con AWS X-Ray para tracing distribuido.
12. Checklist de optimización y despliegue
- Analizar rendimiento con
dotnet-traceyBenchmarkDotNet. - Minimizar allocations y latencia de endpoints.
- Agregar caching (en memoria o Redis).
- Configurar logging estructurado + correlación.
- Dockerizar con imagen ligera (
aspnet:9.0-alpine). - Añadir health checks (
/healthz). - Integrar OpenTelemetry y Application Insights.
- Desplegar en Azure/AWS con CI/CD automatizado.
- Ejecutar test de carga post-despliegue.
- Revisar trazas y métricas para mejorar el siguiente ciclo.
13. Ejemplo: pipeline local → cloud (resumen)
# Build + test
dotnet build -c Release
dotnet test
# Containerize
docker build -t myapp:latest .
# Run local with telemetry enabled
docker run -p 8080:8080 -e OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317 myapp
# Deploy to Azure
az containerapp up --name myapp --resource-group MyRG --image myapp:latest
14. Siguientes pasos
- Aplicar observabilidad avanzada con OpenTelemetry Collector + Grafana
- Integrar CD con ArgoCD o GitHub Actions + Bicep.
- Añadir performance budgets en CI (medir tiempos de endpoints).
- Monitorear SLA y costos en tiempo real.
Módulo 1 – Setup + entorno productivo moderno (.NET 9) Módulo 2 – API REST limpia con ASP.NET Core Módulo 3 – Persistencia con EF Core Módulo 4 – Testing con xUnit Módulo 5 – Frontend y Blazor/MAUI Módulo 6 – CI/CD y Dockerización Módulo 7 – Casos avanzados CQRS + EventBus + Auth Módulo 8 – Arquitecturas distribuidas y resiliencia
¿Te gusta este contenido? Suscríbete vía RSS