Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

19 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 17 de junio de 2025
Pantalla de ordenador mostrando el aviso NETSDK1057 y global.json sugerido como solución del problema

Si os gusta trastear con las previews de .NET en el mismo equipo en el que estáis desarrollando proyectos que usan versiones estables, es posible que al compilar encontréis en la consola o ventana Output de vuestro IDE favorito un mensaje de error parecido al siguiente:

NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy

Básicamente, el sistema nos está informando de que estamos usando un SDK que aún está en fase de pruebas, o preview. Aunque esto no debería ser un problema porque el SDK debería ser totalmente compatible hacia atrás, simplemente es un recordatorio de que no es la versión estable y siempre podríamos encontrarnos algún problema.

Esto ocurre porque los comandos del SDK utilizan la última versión instalada en el equipo, por lo que, si hemos instalado una versión preliminar, será ésta la que se utilice. Podemos comprobarlo fácilmente ejecutando el siguiente comando en consola, que nos mostrará la versión del SDK que se está utilizando por defecto:

 C:\> dotnet --version
10.0.100-preview.5.25277.14

Normalmente, el mensaje NETSDK1057 podemos ignorarlo sin problema, pero si por cualquier motivo queremos eliminarlo o simplemente queremos forzar el uso de una versión determinada del SDK de .NET en algún proyecto o de forma global, podremos hacerlo usando un archivo llamado global.json.

Forzar la versión del SDK

Para forzar el uso de una versión específica del SDK de .NET, bien sea de forma global o bien en un proyecto concreto, lo primero que debemos hacer es determinar qué versiones del SDK tenemos instaladas en nuestro equipo. Para ello, podemos ejecutar el siguiente comando en la consola:

C:\> dotnet --list-sdks
2.1.818 [C:\Program Files\dotnet\sdk]
3.1.426 [C:\Program Files\dotnet\sdk]
6.0.301 [C:\Program Files\dotnet\sdk]
6.0.321 [C:\Program Files\dotnet\sdk]
7.0.120 [C:\Program Files\dotnet\sdk]
8.0.117 [C:\Program Files\dotnet\sdk]
8.0.206 [C:\Program Files\dotnet\sdk]
8.0.411 [C:\Program Files\dotnet\sdk]
9.0.301 [C:\Program Files\dotnet\sdk]
10.0.100-preview.5.25277.14 [C:\Program Files\dotnet\sdk]

Una vez sabemos qué versiones del SDK tenemos instaladas y cuál queremos forzar, lo siguiente es crear un archivo llamado global.json. Su ubicación es importante, porque su ámbito se extiende a todos los proyectos que estén en la misma carpeta o en sus subdirectorios a cualquier nivel de profundidad.

Es decir, si creamos el archivo global.json en la raíz de un proyecto, afectará únicamente a ese proyecto y a sus subproyectos. Si lo creamos en una carpeta superior, por ejemplo en la carpeta de una solución, afectará a todos sus proyectos, que típicamente se encontrarán en subdirectorios. Si lo creamos en la carpeta raíz de un disco duro, afectará a todos los proyectos guardados en él.

El archivo global.json es un archivo JSON con una estructura muy sencilla (podéis consultarla siguiendo este enlace). Básicamente en él indicaremos la versión del SDK que queremos forzar a los proyectos que se encuentren en su ámbito, así como algunas opciones adicionales para personalizar su comportamiento.

Veamos un ejemplo sencillo. Si queremos forzar el uso de la versión 9.0.301 en un proyecto, basta con crear el archivo global.json en su raíz con el siguiente contenido:

{
  "sdk": {
    "version": "9.0.301"
  }
}

La propia CLI de .NET también nos permite hacerlo usando el comando dotnet new global.json --sdk-version <version>, que creará el archivo global.json en la carpeta actual, forzando la versión del SDK que le indiquemos. El contenido del archivo creado será exactamente el mismo que el del ejemplo anterior:

C:\MyProject>dotnet new global.json --sdk-version 9.0.301
The template "global.json file" was created successfully.
C:\MyProject>type global.json
{
  "sdk": {
    "version": "9.0.301"
  }
}

En cualquiera de los casos, si sobre la misma carpeta o alguna de sus subcarpetas consultamos el SDK utilizado por defecto, obtendremos el valor esperado:

C:\MyProject>dotnet --version
9.0.301

C:\MyProject>md Test

C:\MyProject>cd Test

C:\MyProject\Test>dotnet --version
9.0.301

A partir de este momento, dado que ya no estamos usando la versión preview del SDK, el mensaje de aviso habrá desaparecido 😊

Posibles efectos secundarios

Sin duda, usar global.json es una forma muy sencilla de forzar una versión del SDK de .NET en un proyecto o en un conjunto de proyectos. Sin embargo, al hacerlo también podemos estar introduciendo algunos inconvenientes que debemos considerar.

En primer lugar, si forzamos una versión del SDK que no está instalada en el equipo, obtendremos un error al intentar compilar o ejecutar el proyecto. Normalmente no ocurrirá en casos de desarrolladores aislados o si se hace de forma global, pero pueden surgir problemas si trabajamos en un equipo de desarrollo y alguno de los miembros no tiene instalada la versión del SDK que hemos forzado, pues se encontrará con el error al intentar compilar el proyecto.

Por ejemplo, si forzamos en el global.json el uso del SDK 9.0.400, que no está instalado en el equipo, al intentar compilar el proyecto obtendremos un error similar al siguiente:

C:\MyProject>dotnet build
The command could not be loaded, possibly because:
  * You intended to execute a .NET application:
      The application 'build' does not exist or is not a managed .dll or .exe.
  * You intended to execute a .NET SDK command:
      A compatible .NET SDK was not found.

Requested SDK version: 9.0.400
global.json file: C:\MyProject\global.json

También debemos tener en cuenta que al forzar una versión específica del SDK, podemos estar limitando el uso de nuevas características o mejoras que se vayan introduciendo en versiones posteriores del SDK. Es decir, si la versión estable actual es la 9.0.301 y se lanza la 9.0.400, no pasaremos a usar esta última de forma automática, será necesario actualizar el global.json para referenciar la nueva versión.

Por último, a la hora de forzar una versión del SDK, sobre todo si se hace de forma global, también es importante tener en cuenta que cada versión del SDK admite un conjunto de versiones del runtime de .NET. Por ejemplo, si forzamos el uso del SDK 9.0.301, no podremos compilar o ejecutar proyectos cuyo <TargetFramework> en el archivo .csproj sea superior a net9.0, como net10.0 o posteriores:

C:\MyProject>dotnet build
C:\Program Files\dotnet\sdk\9.0.301\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.TargetFrameworkInference.targets(166,5): error NETSDK1045: The current .NET SDK does not support targeting .NET 10.0.  Either target .NET 9.0 or lower, or use a version of the .NET SDK that supports .NET 10.0. Download the .NET SDK from https://aka.ms/dotnet/download

Cómo forzar la última versión estable

Afortunadamente, muchos de estos problemas podemos solucionarlos usando opciones adicionales en el archivo global.json.

Por ejemplo, si queremos que el SDK use la última versión estable instalada en el equipo, sea cual sea su número de versión, podemos usar la opción allowPrerelease. Dado que no usamos la propiedad version para especificar una versión concreta, el sistema simplemente buscará la más reciente que no sea preview:

{
  "sdk": {
    "allowPrerelease": false
  }
}

El valor por defecto de allowPrerelease puede variar según el entorno. En la CLI suele ser true, pero si estamos en Visual Studio, depende de lo que hayamos configurado en la sección Herramientas>Opciones>Entorno>Características de versión preliminar.

Adicionalmente, existe la propiedad rollForward, que nos permite controlar cómo se comporta el SDK cuando no existe la versión del SDK que hemos especificado en la propiedad version, o cómo actuar si existen versiones posteriores a la especificada. Pero esto, si os interesa, lo veremos en un artículo posterior, y mientras tanto, podéis consultar la documentación oficial para más detalles.

Conclusión

En resumen, el uso de global.json nos permite tener un control preciso sobre la versión del SDK de .NET utilizada en nuestros proyectos, evitando sorpresas y mensajes de advertencia relacionados con versiones preliminares. Sin embargo, es importante conocer sus implicaciones y utilizarlo de forma consciente, especialmente en entornos colaborativos.

¡Espero que os resulte útil!

lunes, 16 de junio de 2025
Cementerio con decenas de lápidas de blogs técnicos

Buena cosecha la semana pasada, con mucho contenido interesante 🙂

Destacamos el lanzamiento de la quinta preview de .NET 10, que esta vez incluye cambios en C#, ASP.NET Core, Blazor, .NET MAUI y otras áreas.

Rick Strahl nos enseña a añadir paquetes NuGet en tiempo de ejecución a una aplicación, algo que puede ser muy útil en sistemas con plugins o extensiones.

Vale la pena también echar un vistazo a Next Edit Suggestions, una nueva característica de GitHub Copilot para Visual Studio y Code que sugiere la siguiente edición en el código, lo que puede mejorar la productividad de los desarrolladores.

Shalitha Suranga comparte sus reflexiones sobre el declive de los blogs técnicos y cómo los desarrolladores somos los únicos que podemos hacer algo para que no desaparezcan.

Finalmente, Ricardo Peres nos presenta RazorSharpener, un componente que simplifica la compilación y renderización de componentes Razor en tiempo de ejecución.

Más contenidos interesantes, a continuación.

Por si te lo perdiste...

.NET

martes, 10 de junio de 2025
Componente haciéndole una trascendental pregunta: ¿cómo he sido renderizado?

Desde la aparición de Blazor y sus distintos tipos de hosting de componentes (SSR, Server, WebAssembly), se intentó promover que estos fueran agnósticos respecto a su modo de ejecución. Sin embargo, en la práctica esto no es siempre posible, y en ocasiones necesitamos saber en qué modo se está ejecutando un componente para poder adaptarlo a las necesidades de la aplicación.

Hace más de un año, cuando aún Blazor 8 era la versión más reciente de este framework, vimos por aquí un truco para detectar si un componente Blazor estaba ejecutándose de forma estática (SSR) o interactiva. Y algunos años antes, ya habíamos visto también distintas formas para detectar si un componente interactivo estaba corriendo sobre Blazor Server o Blazor WebAssembly.

Aunque las soluciones propuestas funcionaban bien y solucionaban nuestro problema, eran simplemente trucos (o "hacks", algo retorcidos en algunos casos) para cubrir unas necesidades que no estaban bien resueltas desde el propio framework.

Con .NET 9 esto cambió, y desde esta versión de Blazor ya existen mecanismos nativos para detectar cuándo un componente se ejecuta en modo estático o interactivo, y en este último caso, qué modo de renderizado se está utilizando.

Vamos a ver cómo conseguirlo.

lunes, 9 de junio de 2025
Desarrollador diciéndonos que no con el dedo índice

Aquí está ya la recopilación semanal de enlaces a contenidos a los que vale la pena echarles un vistazo, sobre .NET, patrones, buenas prácticas, acceso a datos, IA, desarrollo web y tooling, entre otros temas.

Esta semana destacamos un interesante post de Chema Alonso sobre cómo saltarse las restricciones de ChatGPT y otros LLMs para obtener imágenes prohibidas utilizando el conocimiento que ya tienen del mundo.

También, José Manuel Alarcón nos cuenta en un detallado artículo las novedades que podemos encontrar en el recién lanzado Angular 20.

Gregor Sutttie nos habla de una de las novedades presentadas en Microsoft Build 2025: los asistentes de actualización de .NET, que nos ayudarán a modernizar nuestras aplicaciones y migrarlas a las últimas versiones.

Me ha llamado la atención el log buffering, una característica de .NET 9 que desconocía y que permite retrasar el momento en que se emiten las trazas. Nos lo cuenta Evgenii Fedorov en su post Emit logs on-demand with log buffering.

Y por último, Braulio Díez nos recuerda la importancia de saber decir que no.

El resto, a continuación 🙂

Por si te lo perdiste...

.NET

martes, 3 de junio de 2025
Desarrolladora ejecutando un archivo .cs con el comando dotnet run

Desde hace ya bastante tiempo, el equipo de .NET está introduciendo mejoras en el SDK para simplificar algunos escenarios y facilitar el acceso a la tecnología de desarrolladores que, o bien están empezando, o bien proceden de otras plataformas.

Una de estas mejoras fueron los top level statements, que permiten escribir los entry points de nuestras aplicaciones C# sin necesidad de definir una clase o un método Main. También las directivas using globales e implícitas ayudaban a reducir el boilerplate necesario para escribir una aplicación C#.

Pero esta vez han ido más lejos 🙂

Con .NET 10, se está trabajando en eliminar toda la ceremonia necesaria para crear y ejecutar una aplicación .NET simple. De la misma forma que se puede hacer en otras plataformas y lenguajes como Node.js o Python, ahora bastará con crear un archivo con extensión .cs y ejecutar el comando dotnet run para compilar y ejecutar el archivo sobre la marcha. Es decir, pasamos de aplicaciones basadas en proyecto a aplicaciones basadas en archivos.

Pero, además, esto abre interesantes posibilidades para la creación de prototipos, pruebas rápidas o incluso para la creación de scripts que aprovechen el poder de .NET y C# sin necesidad de crear un proyecto completo.

Lo vemos en profundidad a continuación.

lunes, 2 de junio de 2025
Desarrollador sentado junto a un agente robótico que le ayuda en su trabajo

Una semana más, aquí tenéis la recopilación de los contenidos que he ido encontrando durante los últimos días. (Afortunadamente) menos enlaces que semanas anteriores, pero aún así, muchas novedades y material interesante sobre .NET, JavaScript, IA, herramientas, patrones y buenas prácticas, entre otros.

Destacamos la reflexión de José Manuel Alarcón, derivada a su vez de un artículo de Dustin Curtis, sobre el impacto del uso de la IA sobre el aprendizaje. Realmente es uno de los temas que más me preocupan sobre el uso masivo de la IA, porque, como siempre se ha dicho, "lo que no se usa, se atrofia". ¿Se va a atrofiar nuestra capacidad de razonamiento, de análisis, de crítica, de creación? ¿Vamos a perder la capacidad de pensar por nosotros mismos? ¿Podríamos quedar relegados a ser la interfaz física de una inteligencia externa que nos diga qué hacer en cada momento? Bueno, esperemos que no, pero debemos estar atentos.

Desde CampusMVP nos llega una alerta, especialmente importante si trabajamos con sitios web y aplicaciones que usan certificados HTTPS: todos caducarán cada 47 días. Nos toca revisar nuestros procesos de renovación y automatizarlos al máximo, tanto por seguridad como por comodidad.

Eladio Rincón actualiza su benchmark de generación de SQL a partir de lenguaje natural usando LLMs.

Interesante también la visión de Microsoft sobre el futuro del proceso de desarrollo de aplicaciones, donde colaboraremos con agentes IA en todas las fases del ciclo de vida: conceptualización, prototipado, generación de código, tests, mejoras, despliegue, monitorización, etc.

Angular 20 ya está aquí: estabilización de APIs, nuevas herramientas de depuración, mejoras en comprobación de tipos, literales en plantillas, server-side y más.

El resto, a continuación.

Por si te lo perdiste...

.NET