
Estrenamos febrero con la recopilación número 595 de enlaces interesantes, cargado de contenidos variados y de calidad relacionado con el desarrollo de software: .NET, ASP.NET, Azure, conceptos, patrones y buenas prácticas, IA, programación web (HTML, CSS, Javascript, frameworks), Visual Studio y herramientas, .NET MAUI, y otros.
Sin duda, la sorpresa y gran protagonista de la semana ha sido el lanzamiento de DeepSeek R1, la IA open source que ha puesto patas arriba a los que hasta ahora se consideraban los reyes del mambo, demostrando que China compite en primera división de los modelos generativos.
También es interesante echar un vistazo bajo el capó de los navegadores, a los mecanismos encargados de interpretar los para interpretar el código HTML y CSS que les llega y crear su representación visual. Aditya Bhattacharya nos lo cuenta el artículo HTML & CSS Deep Dive Part 1: How Browsers Make Sense of Your Code.
Sergey Teplyakov nos recuerda en el post The Dangers of Async Void lo peligroso que puede ser crear métodos o funciones async void
en C#, una práctica que puede llegar a tumbar por completo una aplicación.
El amigo Braulio Díez vuelve con sus historias para no dormir, con el artículo Las migraciones tienen veneno, una visión práctica y realista de lo que hay detrás de estos proyectos que, aunque a primera vista pueden parecer sencillos, tienen bastantes trampas ocultas.
Por último, desde CampusMVP nos llega un post que abre los ojos sobre la realidad del open source: ¿es gratis? ¿quién lo mantiene? ¿quién contribuye? ¿Es sostenible? Muchas preguntas interesantes a las que podremos dar respuesta en el post y vídeo donde José Manuel Alarcón y Jorge Turrado debaten sobre el tema.
El resto de enlaces, a continuación 🙂
Por si te lo perdiste...
- ¡No guardes como cadena el resultado JSON de la llamada a una API si lo único que quieres hacer es deserializarla!
José M. Aguilar - Personalizar la negociación de contenidos en ASP.NET Core MVC
José M. Aguilar
.NET Core / .NET
- When will .NET Framework retire?
Steven Giesel - Implementing AES Encryption With C#
Milan Jovanović - How Fast is Microsoft C#? Discover the Advantages
Dave Ward - Moving from .NET 6 to 8
Joao Correia - Supporting multiple .NET SDK versions in analyzers and source generators
Andrew Lock - The New LINQ Methods from .NET 6 to .NET 9
Anton Martyniuk - Writing a .NET Garbage Collector in C#
Kevin Gosse - The Dangers of Async Void
Sergey Teplyakov - Useful New-ish Features in .NET/C#
David Ramel
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: enlaces

Habitualmente los paquetes NuGet que usamos en un proyecto se registran en entradas <PackageReference>
de su archivo .csproj
. Es un mecanismo sencillo y efectivo cuando trabajamos con un único proyecto o un número reducido de ellos.
Sin embargo, cuando la cosa crece y estamos trabajando con muchos proyectos que usan paquetes comunes cuyas versiones deben estar alineadas, todo se complica un poco, y trabajar con ellos se puede convertir en algo bastante tedioso. Y más aún si no usamos una herramienta visual como NuGet Package Manager de Visual Studio.
Para estos escenarios, NuGet 6.2, lanzado en agosto de 2023 y presente por defecto en todas las instalaciones actualizadas de .NET y Visual Studio, introdujo el concepto de gestión centralizada de paquetes (en inglés, Central Package Management o CPM). Esta funcionalidad nos brinda la posibilidad de definir en un archivo independiente los paquetes utilizados, con sus versiones correspondientes, de forma que todos los proyectos de la solución puedan hacer referencia a él y mantener sus dependencias actualizadas.

Aquí tenemos la entrega número 594 de enlaces a contenidos interesantes que he ido recopilando durante la semana, con mucho .NET, ASP.NET Core, IA, Azure, JavaScript, CSS, herramientas de desarrollo y más.
En esta ocasión me gustaría destacar el post de Neo Kim sobre cómo funciona Bluesky. Me encantan estos posts que detallan los engranajes que hay por detrás de aplicaciones que todos conocemos y que tienen unos requisitos altísimos de escalabilidad y rendimiento.
También me ha resultado muy interesante el post de Milan Jovanović sobre cómo escalar monolitos, porque creo que puede ser de utilidad si tenéis aplicaciones que con el tiempo han ido creciendo más allá de lo que se esperaba en un principio.
También en la sección "cómo funcionan las cosas que usamos todos los días" 😉, el post de Moncef Abboud es muy interesante para profundizar un poco en los algoritmos de compresión más habituales.
Por último, me ha hecho ilusión ver que NDepend sigue evolucionando e introduciendo mejoras para ofrecer perspectivas únicas de nuestras bases de código. Vale la pena echarle un vistazo.
Y ahora, a por el resto...
Por si te lo perdiste...
- Invocar View Componentes usando Tag Helpers en ASP.NET Core MVC
José M. Aguilar - Usar kebab-case en rutas de aplicaciones ASP.NET Core MVC y Razor Pages
José M. Aguilar
.NET Core / .NET
- Why C# Developers Should Also Learn Rust, and What It Can Teach Them
Darren Horrocks - Announcing ConsoleApplicationBuilder, DI in console applications, simply
Peter Ritchie - Accessing MSBuild properties and user configuration from source generators
Andrew Lock - WinForms: Analyze This (Me in Visual Basic)
Klaus Loeffelmann - Seamless Slide Conversion: PowerPoint to Images in C#
Dharanya Sakthivel - Using Roslyn to analyze and rewrite code in a solution
Gérald Barré - The Disposable Pattern in ASP.NET Core
Ricardo Peres - C# Tip: How to create Custom Attributes, and why they are useful
Davide Bellone - Mastering BenchmarkDotNet: The Essential Benchmarking Library for .NET Developers
Jayraj Chhaya - 5 Effective Ways to Navigate PDF Pages in C# Using .NET PDF Library
Chinnu Muniyappan

En general, el uso de expresiones largas debería estar prohibido por ley. Hay pocas cosas que ataquen tanto a la legibilidad de un código como una expresión larga y compleja a la que tengamos que dedicar un buen rato cada vez que intentemos comprenderla. Y no digamos si nos toca modificarla 😱
Aunque esto es aplicable a cualquier tipo de expresión, en este post me voy a centrar en los predicados, que al fin y al cabo representan las condiciones que determinan el comportamiento de una aplicación.
Veamos un ejemplo de if
con un predicado que implementa una condición de negocio necesaria para que un usuario user
pueda realizar una tarea concreta en la cuenta account
:
if (account is not null && account.IsActive && account.HasSubscription
&& account.SubscriptionStartDate <= DateTime.Today && account.SubscriptionEndDate
>= DateTime.Now.AddDays(1) && (account.SubscriptionLevel == "Standard" ||
account.SubscriptionLevel == "Premium") && user.IsActive && (user.HasRole("admin")
|| (user.HasRole("owner"))) && user.AccountId == account.Id)
{
account.ChangePaymentMethod("paypal");
}
Es un poco difícil de leer, ¿verdad? 😅 Bueno, está algo forzado para ilustrar bien el ejemplo, pero seguro que en nuestras bases de código podríamos reconocer fragmentos conceptualmente similares.
Básicamente, la condición anterior verifica si el estado de la cuenta account
es válido para realizar la tarea, comprobando que sea correcta, esté activa, y tenga en vigor una suscripción de nivel "Standard" o "Premium", así como que el usuario user
tenga permisos para hacerlo, comprobando que esté activo, tenga un rol de "admin" u "owner", y pertenezca a la cuenta account
.
Obviamente, no podemos evitar que la lógica de negocio sea compleja, eso no depende de nosotros. Pero sí podemos hacer que la forma de expresarla mediante código sea más sencilla y legible, así que, ¡manos a la obra!

Aquí está la recopilación semanal número 593 de enlaces interesantes, donde podéis encontrar un montón de referencias a artículos sobre C#, .NET, ASP.NET, Azure, desarrollo web, inteligencia artificial, Visual Studio y otros temas 🙂
Destacable el post "Tendencias en programación JavaScript para 2025", de José Manuel Alarcón, donde desvela hacia dónde se dirige el desarrollo JavaScript este año recién estrenado, en términos de herramientas, frameworks, metaframeworks, programación en backend y los nuevos paradigmas impulsados por la irrupción de la inteligencia artificial. Si usáis este lenguaje y su ecosistema, no os lo perdáis.
Los que diseñáis sistemas distribuidos con ASP.NET Core, os puede venir bien echar un vistazo a la introducción de Ricardo Peres a la implementación de trazas distribuidas en ASP.NET Core.
El artículo de Mark Heath sobre el uso de tools de forma segura con LLMs, Using Tools (Safely) with LLMs, me ha sido útil para descubrir que las bibliotecas cliente de Azure OpenAI también tienen la capacidad de ejecutar herramientas, algo que pensaba que había que hacer manualmente o con frameworks más potentes como Semantic Kernel.
Y muy bueno el recopilatorio del equipo de Visual Studio sobre novedades destacables que se introdujeron en el producto durante 2024. Si usáis a diario esta herramienta, echadle un ojo porque hay cosas muy interesantes.
Espero que os sean de utilidad 🙂
Por si te lo perdiste...
- Comprimir el resultado de acciones específicas en ASP.NET Core MVC
José M. Aguilar - Non-nullable property must contain a non-null value when exiting constructor: 7 formas de evitar el warning CS8618 en C#
José M. Aguilar
.NET Core / .NET
- The memory leak in ConcurrentQueue
Oren Eini - Measuring the impact of locks and waits on latency in your .NET apps
Christophe Nasarre - Stop the Leaks: Properly Disposing Objects in .NET
David McCarter - C# foreach: Definition and Best Practices
Stackify Team - Reading compilation options and the C# version in source generators
Andrew Lock - Local inter-process communication over named pipes with ASP.NET Core or StreamJsonRpc in .NET
Anthony Simmon - Comparing Records, Structs, and Classes in C#: When to Use What?
Ali Hamza Ansari - Enhance Your .NET HttpClient with HSTS Support
Gérald Barré - Introducing MSBuild.Sdk.SqlProj 3.0 - create, build, validate, analyze, pack and deploy SQL database projects with .NET 9
Erik Ejlskov Jensen - Mastering C# - Pattern Matching
Jesse Liberty - The Transition of .NET FluentAssertions to Paid Software
Tomasz Sobczak - C# Enum: Definition and Best Practices
Stackify Team - Working with JsonSerializerContext in System.Text.Json and Refit
Tomasz Cielecki

Tras el parón navideño, volvemos a la carga con la primera recopilación de 2025 🙂
Bueno, la frase anterior no es del todo cierta. Por una parte, aunque haya dejado de publicar durante un par de semanas, no he dejado de recopilar enlaces, así que esta edición es especialmente extensa: más de 90 enlaces. Y por otra parte, en realidad sería la segunda recopilación, si contamos la revisión de los contenidos más vistos del blog durante el pasado año que publiqué ayer 😊
Pero bueno, al tema...
Es difícil destacar algo en concreto ante tanto contenido, pero quizás me quedo con el post "The Myth of Perfect Code: Why It’s Hurting You More Than Helping", donde Terrance Craddock reflexiona sobre lo que deberíamos considerar "código perfecto".
También me voy a quedar con algo que, por diferente, me ha llamado la atención: "Unique Solving Method for Rubik's Cube", un método para resolver el cubo de Rubik presentado de forma muy visual. Si sois de los que en los 80 pasasteis horas intentando resolverlo, seguro que como mínimo os resultará curioso 🙂
Por si te lo perdiste...
- Este código C# no compila. ¿Cómo lo hacemos funcionar sin tocarlo?
José M. Aguilar - Crear desplegables desde enums en ASP.NET Core MVC
José M. Aguilar
.NET Core / .NET
- Critical: .NET Install links are changing
Richard Lander - Scheduling Background Jobs With Quartz in .NET (advanced concepts)
Milan Jovanović - Fast build and high security in .NET with Package Source Mapping
Tomasz Sobczak - Back to Basics: Using the Parallel Library to Massively Boost Loop Performance
Rick Strahl - Logging in .NET: Best Practices and Why You Should Love It
Marius Schröder - 10 Reasons to Upgrade to .NET 9
Anton Martyniuk - Vogen: turn your primitives (ints, decimals etc.) into value objects that represent domain concepts
Steve Dunn - StackOverflowException vs. OutOfMemoryException
Sergey Teplyakov - Static Lambda in C# 12 : Performance Improvement
Devesh Omar - C# Null-Conditional (?.) & Null-Coalescing (??) Operators Explained
Ivan Kahl - Automatically format your dotnet code using dotnet format
Josef Ottosson - Think Beyond Synchronous: The Ultimate Guide to Tasks in C#
Chris Woodruff - Moq Unit Testing in .NET Core with xUnit
Jaimin Shethiya - Implementing an interceptor with a source generator
Andrew Lock - Writing a String Numeric Comparer with .NET 9
Khalid Abuhakmeh - .NET 9 upgrade - notnull constraint
Bart Wullems - Exploring CollectionsMarshal for Dictionary
Gérald Barré - C# 12.0: collection expressions
Ian Griffiths - Writing a .NET profiler in C#
Kevin Gosse - Modern C# Part 3 – Switch Expressions
Jesse Liberty

Pues sí, se acabaron las fiestas y aquí estamos de nuevo, volviendo a la rutina. Con el 2025 recién estrenado, ante todo, me gustaría aprovechar la ocasión para desearos que sea un gran año en todos los sentidos🙂
Y para empezar con buen pie, vamos a seguir la tradición de aprovechar este primer post para hacer un breve recopilatorio de los artículos más leídos el año anterior, con idea de que podáis descubrir contenidos que quizás os habíais perdido, reencontraros con algo que os interesó en su momento, o simplemente ver qué contenidos están llamando más la atención al resto de lectores del blog.
Top 10 posts 2024 en Variable Not Found
En décimo lugar, inaugurando el top ten de 2024 tenemos una llamada de atención: el artículo "¡No uses ContainsKey() en un diccionario .NET para ver si existe un elemento antes de obtenerlo!" muestra el impacto en el rendimiento de la doble búsqueda (una para ver si existe el elemento y otra para obtenerlo) y cómo podemos solucionarlo fácilmente con las herramientas que proporciona el propio framework.
Seguidamente, en el noveno puesto de la lista, respondemos a una pregunta bastante habitual cuando empezamos con ASP.NET Core: ¿por qué mi aplicación no arranca? En el artículo "No se puede conectar al servidor web 'https', el servidor web ya no funciona y otras pistas de que no has lanzado correctamente tu aplicación ASP.NET Core", además de la respuesta, veremos otros síntomas que nos pueden ayudar a identificar el problema. Spoiler: has olvidado incluir el app.Run()
al final del código de inicialización 😉

Aquí van los enlaces recopilados durante la semana pasada, en lo que será ya la última entrega del año. Volveremos a las tareas de recolección la primera semana de enero, semana arriba o semana abajo (¡soy malo para esto de las estimaciones!😉).
Esta edición incluye enlaces a casi 50 contenidos que me han llamado la atención, aunque me gustaría resaltar especialmente algunos de ellos.
En primer lugar un gran repaso de CampusMVP a los CWE Top 25 de 2024 o, en otras palabras, a los principales agujeros de seguridad que dejamos por detrás los desarrolladores al crear nuestras aplicaciones. Algunos de ellos seguro que los conoces ya, como inyección SQL o XSS, pero hay muchas más perversidades que debemos conocer y evitar.
Muy interesante, como siempre, los resultados publicados por JetBrains sobre el estado del ecosistema de desarrolladores del año que está a punto de terminar, obtenidos de una encuesta a más de 23.000 developers de todo el mundo. Aquí encontraréis información valiosa sobre los proyectos en los que más trabajamos, qué lenguajes son los más utilizados en distintas áreas, qué herramientas son las preferidas, o si seguimos pensando que la IA nos va a quitar el trabajo a todos los desarrolladores antes de acabar totalmente con la humanidad, o si en cambio es una gran aliada 😉
Por último, también me parece destacable los anuncios que Microsoft ha dejado caer hace unos días: la disponibilidad de un nuevo plan gratuito de GitHub Copilot para los usuarios de Visual Studio y Visual Studio Code. Bueno, obviamente tiene sus limitaciones, pero es un buen punto de partida para los que aún no habéis podido probarlo o no tenéis acceso a licencias superiores.
Por último, aprovecho también para desearos a todos unas muy felices fiestas. Disfrutad de la mejor compañía posible y pasadlo bien, pero eso sí, sin excesos, que luego vienen los arrepentimientos... 😉
Por si te lo perdiste...
- Serialización polimórfica con System.Text.Json
José M. Aguilar - Cómo saber si un nivel de traza está activo en aplicaciones ASP.NET Core/MVC
José M. Aguilar
.NET Core / .NET
- .NET Framework Migration to .NET 9
Derek Comartin - Some news about .NET 10: BackgroundServices and new String Comparer
Steven Giesel - Deep C# - The Perils of the C# Parallel For
Mike James - How and why to write mutation tests in C#
Daniel Ward - Special properties in .NET projects
Alexandre H. T. R. - Deserializing JSON to a string or a value
Phil Haack - Functional Programming With C# - Make Dictionaries Functional!
Simon Painter - C# 13 and .NET 9: Personal Highlights
Dmytro Misik

A principios de siglo, con un C# aún bastante primitivo, las propiedades que almacenaban datos en una clase teníamos que definirlas siempre usando un backing field, es decir, un campo privado que almacenaba el valor, y accediendo a él mediante métodos getter y setter. Es decir, algo así:
public class Customer
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
...
}
Esto cambió en 2007 con la llegada de las propiedades automáticas, una maravilla para nuestros cansados dedos, que desde entonces usamos en la mayoría de ocasiones. Gracias a ellas, podemos definir una propiedad sin tener que implementar sus métodos accesores ni su campo privado correspondiente, porque el compilador se encargaba de crearlos por nosotros. De esta forma, código anterior quedaba así:
public class Customer
{
public string Name { get; set; }
...
}
En realidad, se trataba sólo de un azucarillo sintáctico. Por detrás, el compilador está generando el campo privado y transformando nuestro código para utilizarlo; de hecho, el código generado de la clase anterior es algo así (algo simplificado para que se pueda leer mejor):
public class Customer
{
private string <Name>k__BackingField;
public string Name
{
get { return <Name>k__BackingField; }
set { <Name>k__BackingField = value; }
}
}
Aunque obviamente usar propiedades automáticas es mucho más cómodo que la opción anterior, tiene un inconveniente: no tenemos forma de acceder al campo generado por el compilador, algo que puede resultar interesante si nos interesa realizar algún tipo de validación o lógica adicional en el getter o setter más allá de simplemente devolver o asignar el valor.
Por ejemplo, imaginemos que queremos que el nombre de nuestro cliente siempre esté en mayúsculas. Con una propiedad automática, simplemente no podemos hacerlo, y tendremos que recurrir a las verbosas propiedades tradicionales con backing fields.
Y aquí es donde entran en escena las propiedades semiautomáticas...

Esta semana la cosecha ha sido especialmente prolífica y traemos más de 70 enlaces a contenidos que creo que vale la pena echar un vistazo, como siempre, categorizados por área de interés: .NET, ASP.NET Core, Azure, patrones y buenas prácticas, acceso a datos, inteligencia artificial, programación web (HTML, CSS, Javascript...), herramientas de desarrollo, .NET MAUI y otros.
Como vengo haciendo últimamente, me gustaría destacar el gran post de José Manuel Alarcón sobre técnicas de carga especulativa en páginas web que te ayudarán a mejorar el rendimiento de las aplicaciones.
Muy bueno también el deep dive de Ricardo Peres sobre los tokens de cancelación de tareas, a veces unos grandes desconocidos.
Por último, dos avisos a navegantes: primero, David Grace nos recuerda que en .NET 9, los proyectos de APIs ya no incorporan por defecto Swagger y propone algunas alternativas, y, segundo, Steve Smith alerta de los peligros de usar eventos de .NET en aplicaciones ASP.NET Core y aporta opciones para conseguir lo mismo.
Todo esto, y mucho más, a continuación...
Por si te lo perdiste...
- Binding de parámetros en Minimal APIs con BindAsync
José M. Aguilar - Añadir automáticamente maxlength a inputs usando tag helpers en ASP.NET Core MVC
José M. Aguilar
.NET Core / .NET
- Announcing .NET Community Toolkit 8.4
Sergio Pedri - Understanding Multidimensional Arrays in C#
Rohan Rao - Recurring Tasks in .NET C# : All options explained
Zied Rebhi - Why IActorRef.Tell Doesn't Return a Task
Aaron Stannard - Manually Implementing an Identity Store for Asp.Net Identity
Paul Michaels - Extracting Icons From A Windows DLL Or EXE With C#
Den Delimarsky - LINQ might get a "left join" operator in .net 10
Steven Giesel - Using vectorization in C# to boost performance
Brant Burnett - Inside a Where() - Understanding IEnumerables
James Curran - Object Pools in C#: Examples, Internals and Performance Benchmarks
Alexey Fedorov - Invoking Async Power: What Awaits WinForms in .NET 9
Michael Taylor - Using the YamlDotNet source generator for Native AOT
Andrew Lock - How To Replace Exceptions with Result Pattern in .NET
Anton Martyniuk - Easily Convert Excel to HTML in 3 Steps With C#
Kurmitha Manickhaperumal - Ultra: An advanced profiler for .NET Applications on Windows
Alexandre Mutel - The State of Aspect-Oriented Programming in C# [2025]
Metalama Team - What's New in .NET 9 and C# 13
Ricardo Peres - C# 12: The Experimental Attribute
Thomas Claudius Huber - Meet TUnit: The New, Fast, and Extensible .NET Testing Framework
Sander ten Brinke - The Ultimate Guide to .NET Environment Variables
Hatim Rih - Efficient searching in .NET with SearchValues
Bart Wullems - The attribute OverloadResolutionPriority in .NET 9 and C# 13
NDepend Team - More Testing Tips With C#
Roman Stoffel - MessagePack for C# v3 Release with Source Generator Support
Yoshifumi Kawai - .NET Cancellation Tokens
Ricardo Peres - Avoid Using C# Events in ASP.NET Core Applications
Steve Smith

Aunque un día más tarde de lo normal debido al puente, aquí van los tradicionales enlaces recopilados durante la semana pasada. Como es habitual, la mayoría de los enlaces son a contenidos en inglés, pero también hay algunos en español que me gustaría destacar en esta ocasión.
Por una parte, Jose Manuel Alarcón explica cómo clonar superficialmente un repositorio GIT (shallow clone) para obtener sólo los últimos commits y ahorrar tiempo y espacio en disco.
También muy interesante el post de Braulio Díez, donde reformula la clásica regla del Boy Scout y, quitándole algo de épica romántica, nos recuerda que a veces no siempre es buena idea tocar donde no debemos, o hacerlo de cualquier forma.
Y ahora, vamos a por el resto...
Por si te lo perdiste...
- Eliminaciones y actualizaciones masivas (bulk deletes/updates) con EF Core 7
José M. Aguilar - Confluencia de ramas en el pipeline de ASP.NET Core
José M. Aguilar
.NET Core / .NET
- From .NET 6 to .NET 8, my migration experience:Fixing missing x-forwarded headers in .NET 8 isolated Azure Functions
Anthony Giretti - Using Testing.Platform with NET 9
Dennis Frühauff - Polymorphic deserialization with YamlDotNet
Anthony Simmon - Faster Dictionary in C#
NDepend Team - C# Tip: 2 ways to generate realistic data using Bogus
Davide Bellone - Lesser known CLR GC Handles
Austin Wise - Typemock Isolator 9.3.3: Embracing .NET 9 and C# 13 with AI Testing Capabilities
Eli Lopian - Choosing the Best Mapping Library for Your .NET Core Project
Muthukumar Thevar - C# Advent: No one loves the .NET Core name anymore
Stephen Cleary - Metadata Consulting [dot] ca: Get the number of columns in an HTML Table using Regex
Metadata Consulting

Hoy me voy a salir un poco de las temáticas habituales para compartir un pequeño truco que llevaba buscando desde hace meses, pero que hasta ahora no había tenido tiempo de investigar.
Como seguro os ocurre a muchos de vosotros, tengo un par de cuentas de Gmail (personal y profesional) y estoy habitualmente saltando de una a otra para gestionar los correos y calendarios. He intentado durante bastante tiempo usar herramientas de escritorio de Windows para gestionar el mail y la agenda de ambas cuentas, pero no he conseguido dar con ninguna que me convenciera del todo, así que he llegado a la conclusión de que realmente la mejor interfaz para Gmail o Google Calendar está en la web.
Pero por otro lado, no me gusta usarlas directamente desde el navegador, así que la opción de instalarlas como aplicaciones web progresivas (PWA) me parecía la mejor solución. Basta con acudir a la página que queremos instalar, por ejemplo https://mail.google.com, abrir el menú de Chrome, acceder a la opción "Enviar, guardar y compartir > Instalar página como aplicación...
" y listo. Durante el proceso, incluso se nos pregunta si queremos anclar la aplicación a la barra de tareas, así que podremos tener muy a mano un acceso directo a la aplicación.
El problema es que, al instalarlas, se abren siempre con el usuario de Google que tengamos configurado como por defecto. En la práctica, la aplicación anclada se abrirá siempre con la misma cuenta, que es aquella con la que nos logamos primero en el navegador. Y esto es un problema si queremos tener acceso rápido a varias cuentas, como es el caso.

Es lunes, así que vamos a por los enlaces interesantes de la semana. Quizás algo más escasos que otras veces, probablemente debido a la festividad de acción de gracias del otro lado del charco, pero aún así tenemos una buena colección 🙂
Esta semana, me ha llamado la atención a una interesante pregunta: ¿cuánta memoria necesitarías para ejecutar un millón de tareas concurrentes? Así a ojo es imposible saberlo, pero hay quien ha hecho la prueba con muchos lenguajes, y vemos que C# no sale nada mal parado.
También es un must read el post "¿Y qué trae de nuevo Angular 19?", donde Jose Manuel Alarcón se ha tomado la molestia de recopilar todas las novedades y explicarlas con gran detalle.
Por último, mi descubrimiento de la semana: los bloques de alertas en Markdown. Markdown es mi formato favorito para escribir un montón de cosas (entre otras, los posts de este blog) y era algo que desconocía y me ha parecido bastante interesante y práctico.
Y ahora, a por el resto de enlaces. ¡Espero que los disfrutes! 😊
Por si te lo perdiste...
- Usar dos claves distintas para buscar en un diccionario de .NET
José M. Aguilar - Ramificar el pipeline de ASP.NET Core con Map() y MapWhen()
José M. Aguilar
.NET Core / .NET
- Introducing Microsoft.Extensions.VectorData Preview
Sarosh Wadia - How to Create SVG Files Programmatically in C# .NET
Paarisha Rana - Fire-and-Forget Methods in C# — Best Practices & Pitfalls
Syed Shahriyar - What's new in .NET 9? Key features you need to know!
David Grace - How to Create Command Line Console Applications in .NET
Anton Martyniuk - How to Schedule and Automate C# .NET Reports
Alec Gall - C# 12.0: inline arrays
Ian Griffiths - Checking whether a URI refers to a Web site root
Raymond Chen - idunno.Bluesky: A .NET class library for the the Bluesky social network
Barry Dorrans

Cuando estamos usando alguna clase de .NET en nuestro código, a veces tenemos interés o necesidad de ver qué hace por dentro, para lo que nos gustaría tener acceso rápido a su código fuente. Aunque los IDEs modernos disponen en muchos casos de herramientas o extensiones que lo permiten, está bien saber que hay otras fórmulas sencillas para conseguirlo muy rápida y cómodamente.
Hace poco me he topado con una de ellas, que me ha parecido muy útil y quería compartirla con vosotros, por si hay alguien más que aún no la conoce: la página https://source.dot.net.

Una semana más, vamos con los contenidos interesantes que he ido encontrando por la red. Esta vez, entre los más de 50 enlaces de la entrega, me gustaría destacar tres de ellos.
En primer lugar, el trabajazo de José Manuel Alarcón para resumir todas las novedades de .NET 9 en un único y magnífico artículo. Si queréis poneros al día en unos minutos, no os lo perdáis.
También me ha resultado interesante el post sobre Web Share, una API JavaScript que desconocía, sencillísima de utilizar, relativamente bien soportada en los navegadores, y que puede sernos útil para facilitar la compartición de contenido en nuestras aplicaciones web.
Por último, a modo de homenaje porque durante años ha sido una valiosa fuente de contenidos e información para muchos, me gustaría destacar la semi-despedida de CodeProject, un sitio que si lleváis unos añitos en esto seguro que habéis visitado más de una vez para consultar algunos de sus casi 66.000 artículos técnicos para desarrolladores. Aunque de momento seguirá en línea en modo de sólo lectura, de alguna forma, el post CodeProject is changing anuncia el fin de una era.
Y ahora, vamos con el resto de contenidos que, como siempre, espero que os resulten interesantes.
Por si te lo perdiste...
- Patrones de listas (list patterns) en C# 11
José M. Aguilar - Archivos estáticos en aplicaciones ASP.NET Core (II)
José M. Aguilar
.NET Core / .NET
- .NET 9 ya está aquí: qué novedades trae y qué esperar de esta versión
José M. Alarcón Aguín - How to Turn On Features in .NET and C# Without Redeploying: Exploring Feature Flags and A/B Testing
Ottorino Bruni - Install and use Microsoft Dot NET 9 with the Raspberry Pi
Peter Gallagher - Early Binding and Late Binding in C#
Karthikeyan N. S. - C# 13 - New features and how you can use them now!
David Grace - Boost Your .NET Projects: Unleashing the Power of Spargine’s Numeric Extension Methods
David McCarter - How to Effectively Use Formulas in Excel Using C#
Kurmitha Manickhaperumal - How to Benchmark Your Code in C#
Grant Riordan - Embeded languages in string values supported by Roslyn
Gérald Barré - Schedule Background Job using Quartz.NET
Ali Hamza Ansari - dotnet scaffold - Next Generation Project Creation for .NET
Sayed Ibrahim Hashimi - Easy logging management with Seq and ILogger in ASP.NET
Davide Bellone

Me encanta LINQ. Bueno, ciertamente la sintaxis de consultas integrada en el lenguaje no la uso desde hace muchísimos años, pero los métodos de extensión que proporciona son una maravilla para recorrer y operar sobre colecciones de datos en memoria o almacenados en sistemas externos.
LINQ ha sido uno de los objetivos de .NET 9. Además de mejorarlo internamente y optimizar su rendimiento (en algunos casos, considerablemente), se han incluido tres nuevos métodos, CountBy()
, AggregateBy()
e Index()
, que amplían las posibilidades que teníamos hasta el momento, simplificando la escritura de código y aumentando su legibilidad en algunos escenarios.
Vamos a verlos en detalle.

Como todos los lunes, vamos con los enlaces a contenidos interesantes que he ido encontrando por la red.
Esta semana se ha publicado .NET 9, por lo que tenemos bastantes contenidos relacionados con el lanzamiento y novedades que encontramos en la nueva versión.
Aparte, me ha llamado la atención el post "Understanding LLMs from Scratch Using Middle School Math" de Rohit Patel, que explica cómo funcionan los modelos de lenguaje de gran tamaño (LLMs) de forma sencilla, sin grandes complicaciones matemáticas. Muy recomendable para comprender lo que se cuece bajo el capó de estas tecnologías tan fascinantes.
Y en la sección "hay gente pa tó", me ha parecido curioso el artículo "HTML: The Programming Language", una implementación de un lenguaje Turin completo con sintaxis HTML. Muy útil no parece, pero desde luego es original 😉
Por si te lo perdiste...
- ¡No uses List<T> si siempre vas a buscar por clave en los elementos en una colección!
José M. Aguilar - Archivos estáticos en aplicaciones ASP.NET Core (I)
José M. Aguilar
.NET Core / .NET
- Announcing .NET 9
.NET Team - Calling methods is easier and faster with C# 13 params collections
Kathleen Dollard - Nullable Reference Types in
Tomáš Grošup - Consuming VSIX metadata from C#
Daniel Cazzulino - How to Use Pointers in C#
Konstantinos Polychronopoulos - Functional Programming in C#: The Practical Parts
Milan Jovanović - Traversals
Mark Seemann - How to Set Semantic Versioning for .NET Core Apps and Libraries
Naveed Ausaf - Exploring C# Records and Their Use Cases
Ali Hamza Ansari - Building Rock-Solid Business Logic and Validation Rules in .NET Workflows
Hatim Rih - .NET and C# Versions - 9/13 Update
Niels Rasmussen - Authentication and Authorization Enhancements in .NET 9.0
Andrea Chiarelli - Jeremy Bytes: The C# "field" Keyword and Visual Studio Tooling
Jeremy Clark - Day-0 Telerik Support for .NET 9
Sam Basu

Hace unas semanas estuvimos echando un vistazo a HybridCache
, la alternativa de .NET 9 al sistema de caché distribuida que apareció con .NET Core años atrás. Como vimos entonces, HybridCache
aporta una serie de ventajas respecto a su predecesor, como la protección contra estampidas, la caché multinivel, invalidación por etiquetas, y otras mejoras.
Sin embargo, también introduce algunos inconvenientes que debemos tener en cuenta si queremos sacarle el máximo partido. En esta ocasión, nos centraremos en la penalización debido a excesiva deserialización de objetos de la caché local, un detalle que puede pasar desapercibido pero que puede tener un impacto significativo en el rendimiento de nuestra aplicación.

Con el horno aún humeante, aquí van los enlaces que hemos estado cocinando durante la semana pasada. Espero que estén en su punto y os resulten de provecho 😉
Especialmente destacable el repaso de José Manuel Alarcón a los eventos que podemos usar en JavaScript para detectar que la página actual deja de estar activa, ante la próxima desaparición del evento 'unload'.
Y si queréis experimentar una buena explosión mental, no os perdáis el post sobre Quines, programas cuya salida es su propio código fuente. Un auténtico desafío para mentes inquietas hartas de programación tradicional y algo de tiempo libre😆
Por si te lo perdiste...
- Prueba APIs fácilmente con el nuevo cliente HTTP integrado en Visual Studio 2022
José M. Aguilar - Acceder a arrays en settings JSON de ASP.NET Core
José M. Aguilar
.NET Core / .NET
- Integration Tests en .NET con TestContainers: Pruebas de Base de Datos Aisladas
Isaac Ojeda - Get Ready for .NET Conf 2024!
Jeffrey Fritz - The Legacy Coder's Guide to .NET Conf 2024
DeeDee Walsh - Avoid AutoMapper, Using GitHub Copilot to Map Entities and DTOs in C#
Hatim Rih - yantra: JavaScript Engine for .NET Standard
Akash Kava & otros - Task.Factory.StartNew and long running async tasks
Sergey Teplyakov - Recent updates for NetEscapades.EnumGenerators: interceptors!
Andrew Lock - 6 Effective Ways to Merge PDF Files Using C#
Chinnu Muniyappan - Display SSRS Report in .NET Core Application
Sebastiao Pereira - C# Records
Paul Michaels - Easily Create Dynamic Charts in Excel Using C#
Kurmitha Manickhaperumal - 4 Ways to Implement ICommand
Metalama Team - Getting the Current TabItem when the Tab is not selected in WPF
Rick Strahl - How dotnet.exe resolves and loads the hostfxr library – Exploring the .NET muxer
Steve Gordon - Working With DTO Auto Translators
Peter Ritchie

La clase Task
de .NET dispone de algunos métodos estáticos para trabajar con colecciones de tareas de forma sencilla. Uno de ellos es Task.WhenAll()
, que nos permite esperar a que todas las tareas que le pasemos como argumento se completen, o Task.WhenAny()
para esperar a que finalice sólo alguna de ellas.
Sin embargo, hasta ahora no existía una forma sencilla y directa de procesar las tareas conforme se fueran completando. O bien esperábamos a que todas finalizaran con Task.WhenAll()
, o bien teníamos que crear un bucle que fuera esperando la finalización de la siguiente tarea con Task.WhenAny()
, saliendo cuando todas hubieran acabado.
Afortunadamente, .NET 9 ha añadido el nuevo método llamado Task.WhenEach()
que lo pone más fácil, permitiéndonos detectar sobre la marcha la finalización de las tareas conforme va ocurriendo. Esto nos facilita el proceso de sus resultados secuencialmente, en el orden en el que se completan y sin esperar a que acaben todas.
Vamos a verlo, pero para entenderlo mejor, primero vamos a recordar las opciones que teníamos antes de la llegada de este método.

Ya tenemos aquí los enlaces recopilados durante la semana pasada 🙂
Aunque hay bastante chicha, me ha llamado especialmente la atención que cumpla 21 años una herramienta que sigue siendo imprescindible en el cinturón de muchos de nosotros: Notepad++. ¡Felicidades a Don Ho y los más de 350 colaboradores que lo hacen posible!
Por si te lo perdiste...
- ¿Cuál es el "Bus factor" de tu proyecto?
José M. Aguilar - ¿Compila este código C#? Y si es así, ¿qué retorna?
José M. Aguilar
.NET Core / .NET
- Has Ruby-on-Rails-Style 'Gem Glue-Gunning' Come to .NET?
Aaron Stannard - Personal Identifiable Information Masking in Marten
Jeremy D. Miller - Is the result pattern worth it?
Andrew Lock - Boost .NET 8 Performance with Native AOT
Hatim Rih - Named HttpClient Registrations
Ricardo Peres - 4 Ways to Implement INotifyPropertyChanged – PostSharp Blog
Metalama - C# 12.0: primary constructors | endjin - Azure Data Analytics Consultancy UK
Ian Griffiths

Seguimos analizando las novedades de .NET 9, y en esta ocasión le toca el turno a la actualización en miembros de clases parciales de C# 13.
Las clases o tipos parciales de C# están con nosotros casi desde los inicios de .NET, desde los tiempos de C# 2.0. Como sabemos, éstas permiten dividir la implementación de un tipo en varios archivos. Su existencia se debía a varios motivos:
- Permitir a los desarrolladores trabajar en clases de forma concurrente sin bloquearse (recordemos que por aquellos tiempos aún pululaban por ahí infames sistemas de control de código fuente como SourceSafe).
- Trocear clases extensas para facilitar su comprensión y mantenimiento.
- Y, el que es más importante, posibilitar el uso sencillo de herramientas de generación de código que, de alguna forma, tuvieran que completar la implementación de código del usuario.
Acompañando a las clases parciales, se introdujo también el soporte para métodos parciales. Aunque su uso era limitado y podía depararnos algunas sorpresas, eran útiles para comunicar de forma segura distintos fragmentos de la clase. Básicamente, consistía en que una porción de una clase podía definir un método e invocarlo desde su código, delegando a otras porciones su implementación. Si no se implementaba en ninguna otra parte, simplemente no se generaba el código de la invocación.
Veamos un ejemplo del uso de estas características:
// Archivo: Ejemplo.Main.cs
public partial class Ejemplo
{
// El método parcial se declara sin implementación...
partial void Log(string msg);
public void RealizarAlgo()
{
hacerAlgoComplejo();
Log("¡Ojo!"); // Usamos el método
// parcial declarado antes
}
}
// Archivo: Ejemplo.Log.cs
public partial class Ejemplo
{
partial void Log(string msg)
{
Console.WriteLine(msg);
}
}
Pues bien, casi dos décadas más tarde, los tipos parciales van a recibir algunas actualizaciones interesantes en C# 13, posibilitando que, además de métodos, puedan definirse propiedades parciales.

Aquí tenéis los enlaces recopilados durante la semana.
En esta ocasión, creo que como mínimo vale la pena echar un vistazo a lo nuevo de Anthropic, que sorprende especialmente con computer use, una vuelta de tuerca más para la automatización de tareas con nuestro ordenador. Es increíble que hace sólo unos meses, todas estas novedades que van apareciendo sólo podrían haber cabido en la ciencia ficción...
También muy interesante el movimiento de JetBrains, facilitando el uso gratuito de sus IDEs WebStorm y Rider para proyectos no comerciales 🙂
¡Que los disfrutéis!
Por si te lo perdiste...
- Eliminar el encabezado "X-Powered-By" en ASP.NET Core
José M. Aguilar - Cómo enviar mensajes a la consola del navegador desde Blazor
José M. Aguilar
.NET Core / .NET
- .NET 9 Feature Switches: Trimming the Fat (Like Your Code, Not You)
Cheyenne Sokkappa - Sending Messages to the Original Sender with Wolverine
Jeremy D. Miller - Adding more extensions to Result<T>
Andrew Lock - What are the SOLID Principles in C#? Explained With Code Examples
Danny Adams - Upgrade Your Windows Forms .NET Projects to the Latest .NET Version for Enhanced Security
Shyam Gupta - 10 Most Frequently Asked Questions About JWT in .NET & Implementing JWT Authentication in ASP.NET Core – ArgosCo .net Development Blog
Hatim Rih - A Brief Introduction to the .NET Muxer (aka dotnet.exe)
Steve Gordon

Una de las novedades más destacables de .NET 9 es, sin duda, el nuevo sistema de caché híbrida (Hybrid cache), una puesta al día del sistema de caché distribuida que nos acompaña desde las primeras versiones de .NET Core, y al que iban haciendo falta ya algunas mejoras.
Este nuevo sistema está construido encima de la infraestructura de caching existente (Microsoft.Extensions.Caching
), añadiendo mejoras que hacen que su uso sea más sencillo y contemplando de serie funcionalidades que antes nos veíamos obligados a implementar manualmente.
Vamos a echarle un vistazo a sus principales características :)
Disclaimer: lo que vamos a ver a continuación está basado en .NET 9 RC2, por lo que todavía es posible que haya cambios en la versión final.

Como todos los principios de semana, aquí va la lista de enlaces recopilados durante los últimos siete días. Hay bastantes cosas que me han llamado la atención en esta ocasión; entre otros, he descubierto que Visual Studio incluye un visualizador de JWT integrado, el atributo [OverloadResolutionPriority]
de .NET 9/C#13, y también me he preguntado cuántos son muchos índices en una tabla SQL 😕
Por si te lo perdiste...
- Añadir o eliminar encabezados de respuesta en ASP.NET Core y Core MVC
José M. Aguilar - Obtener el valor de parámetros de la query string con JavaScript
José M. Aguilar
.NET Core / .NET
- Runnable examples
Sergio León - Trace sampling in SerilogTracing
Nicholas Blumhardt - What's new in System.Text.Json in .NET 9
Eirik Tsarpalis - Safety and simplicity with LINQ
Andrew Lock - C# Tip: IEnumerable vs ICollection, and why it matters
Davide Bellone - Understanding OverloadResolutionPriority attribute in C# 13
Gérald Barré - What's new in .NET 9: Cryptography improvements
Ali Hamza Ansari - Automatic Upgrade of .NET and External Dependency Versions, Converting Assembly to Package References and More
Dennis Garavsky - .NET 9.0 LINQ Performance Improvements
NDepend Team - Extending MediatR with publishing strategies
Fati Iseni

Cada vez que llega una nueva versión del framework, todos estamos ansiosos por conocer las novedades, especialmente las más espectaculares. Sin embargo, a veces hay pequeñas mejoras que, sin ser revolucionarias, nos pueden resultar útiles en algunos escenarios.
El modificador params
permite especificar que un método o función acepta un número variable de argumentos, como en el siguiente ejemplo, donde vemos una función Sum()
que puede ser invocada con cualquier número de valores:
// Declaración de la función:
int Sum(params int[] values)
{
return values.Sum();
}
// Ejemplos de uso:
Console.WriteLine(Sum(1)); // Enviamos un único valor -> "1"
Console.WriteLine(Sum(1, 2, 3, 4, 5)); // Enviamos cinco valores -> "15"
Console.WriteLine(Sum()); // No enviamos elementos, se recibirá un array vacío -> "0"
Console.WriteLine(Sum([1, 2, 3])); // Aquí pasamos un array directamente -> "6"
Hasta ahora, el parámetro param
sólo podía ser un array, lo que limitaba un poco su uso. Por ejemplo, no podríamos llamar a la función Sum()
pasándole directamente un List<int>
o un IEnumerable<int>
sin convertirlos antes a array porque fallarían en tiempo de compilación, al no tratarse de un int[]
, que es el tipo del parámetro esperado.
¿Qué ha cambiado?

Aquí tenemos la recopilación de enlaces de la semana. Entre ellos, me han llamado especialmente la atención los datos que muestra Trevor I. Lasn en su artículo sobre el factor edad en el mundo tecnológico, probablemente porque estoy en el 15% del que habla, los desarrolladores que vuelan ya por encima de los 45 tacos 😆
Y aparte, como siempre, un poco de ASP.NET Core, datos, IA, programación web y otros temas que espero que os resulten interesantes 🙂
Por si te lo perdiste...
- Custom middlewares en ASP.NET Core
José M. Aguilar - ¡No uses Replace() para eliminar los guiones de un GUID en .NET!
José M. Aguilar
.NET Core / .NET
- .NET 9 Release Candidate 2 is now available!
.NET Team - Embedding Python into your .NET project with CSnakes
Tony Baloney - Centralize your packages in .NET with NuGet
Steven Giesel - Unleashing .NET 9: Key Performance Boosts and Pitfalls Compared to .NET 8
David McCarter - .NET 8 vs .NET 9: What's the Difference and Should you Migrate?
Cheyenne Sokkappa - Replacing Exceptions-as-flow-control with the result pattern
Andrew Lock - How To Simplify Assertions in Unit and Integration Tests with Verify in .NET
Anton Martyniuk - Domain Events with .NET
Visit profile - Avoiding Repetitive Code With Metalama
Gael Fraiteur - Using Windows Error Reporting in .NET
Kevin Gosse - Have you ever memory-profiled in a unit test?
Dennis Frühauff - Engineering the Scalable Vector Extension in .NET
Kunal Pathak - Typed chat completions with OpenAI and .NET 9
Daniel Cazzulino - Cancellation, Part 6: Linking
Stephen Cleary - Advanced Unit Testing in .NET with xUnit, NSubstitute, and AutoFixture: A Deep Dive into my HangfireDemoApi
Juan Luis Guerrero

Probablemente, todos hemos usado en algún momento el método Guid.NewGuid()
de .NET para generar identificadores únicos globales. Y muchos hemos sufrido con el problema que supone su (pseudo) aleatoriedad, principalmente cuando necesitamos ordenarlos... sobre todo si su destino final es acabar siendo el campo clave de una base de datos relacional.
Pero pocos éramos conscientes de que el método Guid.NewGuid()
de .NET retorna un GUID versión 4, y que existen otras versiones de UUID (¡hasta 8!) que pueden resultar más beneficiosas en determinados escenarios.