El equipo de un cliente — tres desarrolladores, un plan de seis semanas, un objetivo claro: sacar su aplicación interna de operaciones de .NET Framework y llevarla a .NET moderno. A las dos semanas, chocaron con una pared. Su pantalla de inicio de sesión en realidad no tenía pantalla de inicio de sesión. Usaba autenticación de Windows: los empleados abrían la aplicación ya identificados, porque Windows ya los había reconocido en el dominio. Nadie lo había anotado como una "función" porque nadie lo pensaba como tal — siempre había funcionado así. Cuando se pusieron a ver cómo llevar eso a .NET moderno, la respuesta no fue una casilla para tildar. Necesitaba trabajo real de diseño, no un cambio de configuración.
Ahí es donde normalmente me llaman. No porque la migración en sí sea imposible — casi nunca lo es — sino porque un equipo se topó con alguna de un puñado de cosas que dan por sentado a .NET Framework y no se trasladan solas. Quiero recorrer la lista real de estas cosas: qué es cada una en realidad, por qué traba una migración que parecía directa, y por qué cada una de ellas tiene un camino conocido hacia adelante. Ninguna es motivo para detenerse.
System.Web y HttpContext
Las aplicaciones clásicas de ASP.NET están construidas sobre System.Web — la librería que da acceso a HttpContext, módulos de solicitud y handlers. ASP.NET Core moderno no tiene System.Web. Tiene su propio pipeline de solicitudes, distinto. Si su aplicación accede a HttpContext.Current desde el fondo de la lógica de negocio — y en bases de código antiguas, suele hacerlo, repartido en docenas de archivos — ese código no se puede simplemente recompilar contra .NET moderno. Hay que encontrarlo, entenderlo y reescribirlo usando el equivalente moderno.
Es trabajo real, pero es trabajo mecánico. Microsoft documenta adaptadores específicamente para esta situación, que permiten correr código viejo y nuevo en paralelo mientras se van moviendo piezas de forma gradual, en lugar de necesitar una reescritura de un solo día.
Servicios WCF
Windows Communication Foundation fue el framework de Microsoft para construir integraciones orientadas a servicios bajo .NET Framework. .NET moderno no incluye un servidor WCF. Si un sistema interno, una integración con un socio de negocio, o una parte de su propia aplicación se comunica por WCF, eso es un punto de decisión real, no una opción de configuración.
Los caminos prácticos son un port mantenido por la comunidad que permite correr un servicio con forma de WCF sobre .NET moderno, o una reescritura de ese servicio específico usando gRPC o una API HTTP simple, que suele ser la mejor movida a largo plazo si el servicio es lo bastante chico como para justificar hacerlo bien. De cualquier manera, esto hay que identificarlo temprano, porque es uno de los pocos obstáculos que de verdad necesita una decisión de diseño y no una conversión mecánica.
Autenticación de Windows y otras APIs exclusivas de Windows
Esto fue lo que atrapó al equipo de mi cliente. La autenticación de Windows, y un puñado de otras APIs específicas de Windows, asumen IIS y Windows de maneras que no se trasladan uno a uno al modelo multiplataforma de .NET moderno. .NET moderno sigue soportando la autenticación de Windows — no desapareció — pero hay que configurarla y conectarla de forma deliberada, como una pieza propia de la migración, no asumiendo que "viene incluida" como pasaba en Framework.
La solución acá no es exótica. Es planificación: saber que esta dependencia existe antes de empezar, para que sea una tarea programada y no una sorpresa de dos semanas que frena todo el proyecto.
Librerías de terceros sin versión para .NET moderno
A veces el obstáculo no es su código, sino el de un proveedor. Un motor de reportes, una librería de códigos de barra, un generador de PDF viejo: si la última actualización fue en 2016 y solo se publica para .NET Framework, .NET moderno no puede usarla directamente, y punto.
Acá las opciones son más acotadas pero igual de reales: buscar una alternativa para .NET moderno (a menudo existe, el ecosistema maduró bastante), aislar la dependencia detrás de una interfaz interna chica para que cambiarla más adelante no repercuta en toda la aplicación, o, en una minoría de casos, dejar esa pieza puntual corriendo sobre Framework detrás de una llamada interna desde la aplicación nueva — poco elegante, pero funcional como puente mientras el resto avanza.
Configuración basada en web.config y despliegue a un solo servidor
Menos dramático, pero común: una aplicación cuya configuración vive entera en web.config, ajustada durante años con valores que ya nadie recuerda del todo por qué están ahí, desplegada a mano a un servidor específico. El sistema de configuración de .NET moderno funciona distinto, y el despliegue moderno asume que puede correr en más de un lugar sin tratar cada caso por separado.
Este suele ser el obstáculo más fácil de resolver de toda la lista — cuesta principalmente disciplina: documentar qué hace en realidad cada valor, y después moverlo al nuevo modelo de configuración, en vez de adivinar y esperar que nada se rompa.
Nada de esto es motivo para detenerse
Cada uno de estos puntos tiene solución, y cada uno ya fue resuelto antes por otros equipos. Lo que tienen en común es que ninguno se descubre leyendo el archivo del proyecto — se descubren cuando alguien abre de verdad el flujo de inicio de sesión, la capa de integración, los scripts de despliegue, y se pregunta "¿de qué depende esto en secreto?"
Para eso sirve exactamente una auditoría: encontrar cada uno de estos puntos antes de que un desarrollador se tope con ellos a mitad de un sprint, mapear cuáles aplican a su sistema, y convertir cada uno en una decisión concreta con un plan concreto — en lugar de una sorpresa que frena el proyecto en la segunda semana, como le pasó al equipo de mi cliente.