
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Aspectos a tener en cuenta al crear sitios web públicos
José María Aguilar - Syncfusion Blazor UI components library: un primer vistazo
José María Aguilar
.NET Core / .NET
- Announcing .NET Community Toolkit 8.2! Faster generators, code fixers, performance improvements and more!
Sergio Pedri - C# 11 features I like the most
Neel Bhatt - How to Run an Async Method Synchronously in .NET
Code Maze - Deterministic Finalization in C#: IDisposable and Best Practices
Bradley Wells - A reminder to consider that your context, isn’t the only context (.NET 8 TimeProvider edition)
João Antunes - 10 Awesome C# Refactoring Tips
Assis Zang - Applying the decorator pattern in .NET Core using Castle.DynamicProxy
Bart Wullems - Some basic query support for System.Text.Json
Josef Ottosson
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: enlaces

Atributos como [FromRoute]
, [FromForm]
, [FromQuery]
o [FromBody]
, entre otros, permiten ser muy precisos a la hora de indicar al framework cómo poblar los parámetros de los handlers de nuestros endpoints contruídos con Minimal APIs.
Por ejemplo, en la siguiente API sencilla se puede intuir que el parámetro id
del manejador será obtenido de la ruta, mientras que number
se obtendrá desde la query string:
app.MapPost("/friends/{id}/phones", ([FromRoute] int id, [FromQuery] string number) =>
{
// Añadir un número de teléfono al amigo
});
Y otro ejemplo, en el que usamos [FromBody]
para especificar que el parámetro de tipo Friend
queremos obtenerlo desde el cuerpo de la petición:
app.MapPut("/friends/{id}", ([FromRoute] int id, [FromBody] Friend friend) =>
{
// Actualizar amigo
});

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Cuánto pesa realmente una aplicación Blazor WebAssembly recién creada?
José María Aguilar - Y todavía otras 101 citas célebres del mundo de la informática
José María Aguilar
.NET Core / .NET
- Trabajos en segundo plano en .Net
Fernando Escolar - Property Ordering in C# JSON Serialization
Code Maze - WireMock.NET - Troubleshooting
Cezary Piątek - Short Circuit Evaluation of IF Statements with Await in C#
Code Maze - Covariance and Contravariance in C#
Steven Giesel - Reduce Collection Lookups With ReSharper
Maarten Balliauw - Setting an Absolute Output Path for .NET SDK Projects
Rick Strahl

Versión tras versión, Entity Framework Core sigue introduciendo novedades que lo hacen cada vez más potente y atractivo para los desarrolladores. Sin ir más lejos, EF7, la última entrega disponible, incorporó bastantes mejoras en términos de rendimiento, soporte para columnas JSON, mapeo TPC, mapeo a procedimientos almacenados y muchas otras.
Pero una de las novedades que me resultó más interesante, quizás por ser muy esperada, fue la posibilidad de realizar borrados y actualizaciones de forma masiva sin tener que recurrir a lanzar directamente comandos SQL. O dicho de otra forma, con EF7 podremos ejecutar sentencias DELETE
y UPDATE
sobre la base de datos sin abandonar LINQ :)

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Palabras malditas
José María Aguilar - Analiza tu código a fondo y desde distintas perspectivas con NDepend
José María Aguilar
.NET Core / .NET
- Announcing .NET 8 Preview 3
Jiachen Jiang - Check out new C# 12 preview features!
Kathleen Dollard - Convert HTML to PDF Report in .NET
Abdul Rahman Shabeek Mohamed - How to Do an Inner Join in LINQ?
Code Maze - Run dotnet core projects without opening visual studio
Karthik Chintala - Investigating a crash in Enumerable.LastOrDefault with a custom collection
Gérald Barré - 5 useful extensions for Task<T> in .NET
Steven Giesel - Normalize and compare URLs with C#
Thomas Ardal - Using Application Insights in .NET Desktop Applications
Rick Strahl - Working With Nested Tasks
Pawel Woltschkow - Producing and Consuming Kafka Messages in CloudEvents Format Using the C# SDK
Vasil Kosturski - Why my WireMock mocks aren't working?
Daniel Genezini - C# Tip: Access items from the end of the array using the ^ operator
Davide Bellone - Static Fields Are Evil, If Not Coded Correctly
David McCarter - Upcasting and Downcasting in C#
Code Maze - .NET 8 Performance Edition
Steven Giesel - Converting Strings to .NET Objects – IParsable and ISpanParsable
Christian Nagel - Performance: The Fastest Way to Use Regular Expressions in Microsoft .NET 7
David McCarter - Different Ways to Split a String in C#
Code Maze - C#12 class and struct Primary Constructors
Patrick Smacchia

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- El hombre que inventó el Control-Alt-Suprimir
José María Aguilar - C# source generators: un ejemplo sencillo, paso a paso
José María Aguilar
.NET Core / .NET
- Looking at C# 12 Proposals and Beyond
Michael Shpilt - LINQ on steroids with SIMD
Steven Giesel - Does OpenTelemetry in .NET Cause Performance Degradation?
Martin J. T. - Refactoring Object-Orientation Abusers in C#
Code Maze - WireMock.NET - Introduction
Cezary Piątek - An abstract example of refactoring from interaction-based to property-based testing
Mark Seemann - How to Remove All Whitespace Characters From a String in C#?
Code Maze - Source Generators and Regular Expressions
Steven Giesel - Listing all available ETW events in a .NET application
Gérald Barré - Working with Tuple in C#
A. Yohan Malshika - C# 11.0 new features: Span<char> pattern matching
Ian Griffiths - Pythonnet – A Simple Union of .NET Core and Python You’ll Love
Nick Cosentino

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- C# Source generators: metaprogramación en tiempo de compilación
José María Aguilar - Desmitificando las expresiones lambda (I)
José María Aguilar
.NET Core / .NET
- How to create a NuGet metapackage
Daniel Wertheim - C# Source Generators: How to get build information?
Steven Giesel - Handling CancelKeyPress using a CancellationToken
Gérald Barré - Deep Copy of an Object in C#
Code Maze - Understanding the .NET ecosystem: The introduction of .NET Standard
Andrew Lock - Primary Constructors with C#
Christian Nagel - Improving multi-platform container support
Richard Lander - How to Delete Elements from an Array in C#
Code Maze - Using the contents of a file to define an MSBuild property
Raymond Chen - C# - Clean up your exception handling logic with Exception Filters
Bart Wullems - Using System.Text.Json to do polymorphic Json conversion in .NET 6
Allan Thraen - Observability in Wolverine
Jeremy D. Miller - Vendor-Agnostic Telemetry Using OpenTelemetry Collector in .NET
Phil Broderick - Change the ServiceLifetime after the service has been added to the .NET ServiceCollection
Niels Swimberghe

A raíz del artículo publicado hace algunas semanas sobre las ventajas de usar diccionarios en lugar de listas, me llegaba vía comentarios un escenario en el que se utilizaba una clase List<T>
para almacenar objetos a los que luego se accedía mediante clave. Lo diferencial del caso es que dichos objetos tenían varias claves únicas a través de las cuales podían ser localizados.
Por verlo por un ejemplo, el caso era más o menos como el que sigue:
public class FriendsCollection
{
private List<Friend> _friends = new();
...
public void Add(Friend friend)
{
_friends.Add(friend);
}
public Friend? GetById(int id)
=> _friends.FirstOrDefault(f => f.Id == id);
public Friend? GetByToken(string token)
=> _friends.FirstOrDefault(f => f.Token == token);
}
Obviamente en este escenario no podemos sustituir alegremente la lista por un diccionario, porque necesitamos acceder a los elementos usando dos claves distintas. Pero, por supuesto, podemos conseguir también la ansiada búsqueda O(1) si le echamos muy poquito más de tiempo.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Formas de relanzar excepciones en C#
José María Aguilar - Cómo crear bibliotecas de clases o proyectos de consola .NET 5 en lugar de .NET Core 3.1
José María Aguilar
.NET Core / .NET
- Adding Dependency Injection to a Console App in .Net 7
Paul Michaels - Loading RSA Keys in .NET & Loading RSA Keys in .NET
Scott Brady - How to Use MemoryStream in C#
Ivan Matec - Too many timers in .NET?
Gérald Barré - Implementing React's UseState in C#
Ricardo Peres - Understanding the .NET ecosystem: The evolution of .NET into .NET 7
Andrew Lock - Caching in .NET with MemoryCache
Steven Giesel - The Top .NET C# UI Controls You Should be Using
GrapeCity Developer Solutions - Iterator Benchmarks That Shocked With Unexpected Results
Nick Cosentino - .NET 8 Preview 2 Unveiled: 5 New Features You Need to Know
ByteHide - .NET Performance Delivers Again for Bing, From .NET 5 to .NET 7
Ben Watson - Secure your .NET cloud apps with rootless Linux Containers
Richard Lander - How to build a URL Shortener with C# .NET and Redis
Niels Swimberghe - .NET Core - Remove older SDKs and runtimes
Bart Wullems - How to Create a Custom JsonConverter in Json.NET
Ahsan Ullah - Leverage 'is not' Operator for Exception Filtering!
Steven Giesel

El pattern matching de C# proporciona la capacidad de analizar expresiones para ver si cumplen determinados "patrones" o presentan características determinadas. Podéis ver algunos ejemplos interesantes en el post Un vistazo a los patrones relacionales y combinadores.
Aunque ya los tengo bastante interiorizados y hago uso de ellos cuando toca, todavía no se me ha dado el caso de necesitar los patrones de listas, introducidos hace unos meses en C# 11. Así que no está de más echarles un vistazo para cuando se dé la ocasión 😉

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Radzen Blazor Components: ¡ahora open source!
José María Aguilar - Usando using, valga la redundancia (C#)
José María Aguilar
.NET Core / .NET
- Announcing .NET 8 Preview 2
Alexandra Barry - .NET 7 SDK built-in container improvements
Laurent Kempé - System.Text.Json Serializing Hierarchical Data
Christian Nagel - Partial Classes In C# And How to Use Them
Code Maze - Solving .NET JSON Deserialization Issues
Khalid Abuhakmeh - Using Trie Class for Efficient Text Pattern Searching in C#
Code Maze - How Async/Await Really Works in C#
Stephen Toub - Immutable Collections in C#
Code Maze - WkHtmlToPdf: Dealing with broken Url Encoded and Extended Character Links
Rick Strahl - Enhancing JPEG, PNG, Text Using C# .NET Part 1
GrapeCity Developer Solutions - Polly with .NET 6, Part 8 - Policy Registry with Minimal APIs, and HttpClientFactory
Bryan Hogan - Discover the New Features of .NET 8: What You Need to Know
ByteHide - Many Ways to make and Deserialize an HTTP GET with HttpClient
Bryan Hogan - Write your own AutoMapper in C#
Steven Giesel

A veces, los problemas de rendimiento de las aplicaciones, o determinadas funcionalidades de ellas, vienen derivados del uso de estructuras incorrectas para almacenar los datos, ya sea en memoria, base de datos o en cualquier tipo de almacén.
En este post vamos a centrarnos en un caso específico que me he encontrado demasiadas veces en código real: el uso indebido del tipo List<T>
cuando sólo nos interesa buscar en esta colección por una propiedad que actúa como identificador único del objeto T
.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Si usas [EmailAddress] y [Url] para validar datos de entrada, ojo: ¡que hace tiempo que ya no validan mucho!
José María Aguilar - 101 formas de saber que tu proyecto está condenado al fracaso
José María Aguilar
.NET Core / .NET
- Gestionando la configuración de nuestras aplicaciones (1/x)
Sergio Navarro Pino - Delegados en C#
Benjamín Camacho - What's new for the WinForms Visual Basic Application Framework
Klaus Loeffelmann - Announcing ImageSharp 3.0.0
Siz Labors - We want your feedback! Introducing Polly v8
Joel Hulen - What really is the Entry Point of a .NET Module?
Washi - Understanding LINQ Deferred, Immediate, Streaming and Non-Streaming Executions
Abdul Rahman Shabeek Mohamed - .NET Console Application with injectable commands
Kees C. Bakker - Validating Connection Strings on .NET Startup
Khalid Abuhakmeh - Testing Roslyn Incremental Source Generators
Gérald Barré - How to Setup Integration Tests in .NET Without a WebApplicationFactory
Paul DeVito - How To Use The yield break Statement In C#?
Muhammed Saleem - How to Find the Caller Method in C#
Code Maze - Implementing the Producer Consumer Pattern with TPL Dataflow
Mark Heath - Alternative Way of Logging With OpenTelemetry Logging in .NET
Phil Broderick - Manipulating CSV Files in .NET
Assis Zang

Si desarrollas APIs, probablemente utilizarás Postman, Fiddler o herramientas similares para probarlas. Cualquier utilidad capaz de lanzar peticiones y analizar la respuesta, incluso basadas en línea de comandos como el desconocido Dotnet HTTP REPL, viene de perlas para ponernos en el lugar del cliente y comprobar cómo responde nuestra API ante determinados parámetros de entrada, o qué se siente al consumirla.
Tiempo atrás, el descubrimiento de la extensión REST client para Visual Studio Code supuso una bocanada de aire fresco en la forma de lanzar peticiones y examinar respuestas, para mi gusto mucho más cómoda que las que estaba acostumbrado a utilizar. Esta extensión permite definir peticiones HTTP en archivos de texto con extensión .http
o .rest
y ejecutarlas de forma realmente sencilla, sin abandonar el IDE.
Pues bien, la última revisión de Visual Studio 2022 (17.5) ha incluido el soporte nativo para este tipo de archivos, así que cada vez lo tenemos más sencillo. Y como es posible que alguno de vosotros aún no lo conozca, vamos a echarle un vistazo ;)

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Programadores con producción neta negativa (NNPP)
José María Aguilar - Trimming de espacios no significativos en Blazor 5
José María Aguilar
.NET Core / .NET
- Get Seamless Network Communication with These .NET Classes
Admir Mujkic - C# Tip: Initialize lists size to improve performance
Davide Bellone - How to Improve Enums With the SmartEnum Library
Code Maze - Extending the System Menu to add advanced commands in .NET
Gérald Barré - What To Be Wary of With Iterators and Collections in C#
Nick Cosentino - Raw Strings, UTF-8 Strings, and Multiline Interpolations – Using C# 11 in Rider and ReSharper
Sasha Ivanova - C# FileStream For Lazy Developers In A Hurry. The Bare Minimum
Gus Pear - Resiliency with Wolverine
Jeremy D. Miller - Speed Up ASP.NET Core JSON APIs with Source Generators
Khalid Abuhakmeh - IEnumerable, ICollection, IList and List
Code Maze - Write a high-quality README for NuGet packages
Lynn Dai - Microsoft Teams' Permission Service migration to .NET 6
Diogo Barbosa

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Iterar con foreach sobre cualquier tipo de objeto con C#9
José María Aguilar - Visualizar archivos de ayuda .CHM descargados de Internet
José María Aguilar
.NET Core / .NET
- C#: enum
Fernando Escolar - Announcing .NET 8 Preview 1
Jeremy Likness - error NETSDK1194: The "--output" option isn't supported when building a solution.
Steven Giesel - Building Functional .NET Applications: a Guide for Choosing between Nahla Davies & Daniel Bryant
- How safe are .NET serialization libraries against StackOverflowException
Nemanja Mijailovic - Refactoring huge C# code base in minutes
Laurent Kempé - Creating a custom Main method in a WPF application
Gérald Barré - List and Span Pattern Matching – Using C# 11 in Rider and ReSharper
Sasha Ivanova - Create Clean Guard Clauses With GuardClauses in C# Code Maze
Code Maze - Resolving the Call Is Ambiguous Error While Using LINQ
Code Maze - C# "var" with a Reference Type is Always Nullable
Jeremy Clark - Getting git version information in your C# code
Steven Giesel - Safer Nullability in Modern C#
Matt Eland - C# 11.0 new features: newlines in string interpolation expressions
Ian Griffiths - Automatic Instrumentation of Containerized .NET Applications With OpenTelemetry
Rahul Rai - How Hangfire Helps Your .NET API Perform Out-of-Process Tasks with Resilience and Speed – Wrapt
Paul DeVito - Windows Forms Binding Improvements in .NET 7 for MVVM Support Edin Kapić
- C# 11–The scoped keyword
Bart Wullems

Aunque muchos de nosotros trabajamos a diario con C#, siempre hay algo nuevo por aprender o formas de utilizar algunas características que nunca se nos habían ocurrido. Siempre.
En un nuevo capítulo de la serie de C# bizarro, hoy os planteo un reto sobre este código:
var sum = (int a, int b) => a + b;
var sub = (int a, int b) => a - b;
var mul = (int a, int b) => a * b;
var result = sum - sub + mul;
Console.WriteLine("Resultado: " + result(3, 2));
¿Compila? Y si es así, ¿qué aparece por consola? ¡No sigáis leyendo! Echad un vistazo al código e intentad averiguarlo antes de ver la solución pulsando aquí :)
Pues sí, este código es totalmente válido y compilará sin problema. Y al ejecutarlo, por consola veremos lo siguiente.
Resultado: 6
En primer lugar el código compila correctamente porque las variables sum
, sub
y mult
, que hemos definido usando expresiones lambda de tipo Func<int, int, int>
, a la postre son simplemente delegados.
Además, los tres delegados tienen la firma idéntica (reciben dos valores int
y retornan un int
), podemos utilizar los operadores de combinación suma "+
" y resta "-
", lo que da lugar a un delegado de multidifusión (multicast delegate).
En nuestro código, creamos el nuevo delegado de multidifusión result
combinando sum
y mult
, que son los dos delegados que se suman. Por otra parte, la resta de sub
es simplemente una maniobra de distracción, pues se intentará eliminar de la combinación un delegado que no existía previamente, por lo que la operación será ignorada.
var result = sum - sub + mul;
Tras ejecutar esta línea, result
será un Func<int, int, int>
cuya invocación provocará que se ejecuten secuencialmente, y por orden de llegada, los delegados que han sido combinados.
Por tanto, cuando se evalúa la expresión result(3, 2)
, se ejecutará primero la función sum(3, 2)
y luego mul(3, 2)
, y será el resultado de esta última la que se retorne finalmente. De ahí obtenemos el 6
que va a la consola.
¿Qué, habías acertado?
Publicado en Variable not found.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Crear componentes de forma dinámica en Blazor
José María Aguilar - 20 desastres famosos relacionados con el software
José María Aguilar
.NET Core / .NET
- Upgrading your .NET projects with Visual Studio
Olia Gavrysh - How to Return a Default Value From a Dictionary in C#
Code Maze - What is .NET, and why should you choose it?
.NET Team - Thoughts on 'What is .NET, and why should you choose it?'
Andrew Lock - Exploring the New Features and Improvements in .NET 7
Vinoth Kumar Sundara Moorthy - How to Get Formatted JSON in .Net Using C#
Code Maze - Async EventHandlers – A Simple Safety Net to the Rescue
Nick Cosentino - Wolverine’s New HTTP Endpoint Model
Jeremy D. Miller - Creating a circuit breaker health check using Polly CircuitBreaker
Jürgen Gutsch - What's On Tap for .NET 8 (Preview 1 Coming this Month)
David Ramel - Digging Into Nullable Reference Types in C#
Shawn Wildermuth - Multipart Form-Data in HttpClient with ASP.NET Core
Code Maze - Prevent accidental disclosure of configuration secrets
Gérald Barré - Removing Manually Installed .NET SDKs from Linux
Bryan Hogan - Creating Visual Studio extensions using Roslyn analyzers
Thomas Ardal - A (performance) quirk with JsonSerializer
Steven Giesel - Getting Started with Generics in .NET
Assis Zang

Hace poco, un alumno de mi curso de Blazor en CampusMVP me preguntaba si, para seguir con las viejas costumbres, desde Blazor Server era posible escribir en la consola del navegador.
Aunque no tiene demasiado sentido hacerlo dado que disponemos de buenas herramientas de depuración, me pareció un ejemplo interesante para aplicar los mecanismos de interoperación de Blazor con JavaScript. Además, quizás interese a alguien más, así que vamos a ver por aquí cómo hacerlo.
Pero antes de meternos en faena, vale la pena decir que lo que veremos no es específico de Blazor Server, sino que también podremos usarlo en Blazor WebAssembly. Los mecanismos básicos de interoperación con JavaScript son idénticos, por lo que en este post veremos cómo implementar un código válido para ambos tipos de hosting.
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: blazor, blazorinterop, blazorserver, blazorwasm

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo tomar el control en el momento de la instanciación de componentes Blazor con IComponentActivator
José María Aguilar - Métodos genéricos en C#
José María Aguilar
.NET Core / .NET
- C# Language Mind map
Steven Giesel - Update to the .NET language strategy
Kathleen Dollard - Simple Secrets for Access to the .NET Record Type
Nick Cosentino - Refactoring Bloated Code in C#
Code Maze - Explicit validation in C# just got simpler!
Oskar Dudycz - Asynchronous Programming Patterns in .NET
Code Maze - Must follow C rules, no exceptions
Eric Sink

Me gusta estar atento a las novedades que van apareciendo el lenguajes y frameworks que nos ayudan a mejorar la forma de hacer las cosas. Lamentablemente, en este mundo tan cambiante no es fácil estar al día en todo, y hay muchas veces que sigo haciendo cosas como siempre aunque existan fórmulas más modernas y mejores para conseguirlo.
Un ejemplo lo he encontrado hace poco, cuando, trabajando con JavaScript, una vez más he tenido necesidad de parsear la URL de la página actual en busca de los valores de los parámetros suministrados en la query string al cargar una página. Lo habitual en estos casos era tirar de Google o StackOverflow y acabar implementado una función parecida a la siguiente:
function getParameterValue(name, url = window.location.href) {
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
Casualmente, en este caso recordé haber leído de pasada sobre la existencia de un "nuevo" objeto de JavaScript que actualmente nos permite hacerlo de forma más sencilla, así que aproveché para ponerme un poco al día al respecto ;)

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo convertir clases en diccionarios clave/valor
José María Aguilar - 12 novedades destacables de Blazor 5.0 (bueno, y algunas más)
José María Aguilar
.NET Core / .NET
- C# HTML Parser
Manthan Koolwal - How to Get Value by Key from JObject in C#
Code Maze - C# All string escape sequences
Metadata consulting - Hot-reload any Serilog sink
Nicholas Blumhardt - C# Tip: do NOT use nameof to give constants a value
Davide Bellone - Basic Windows Machine Hardware information from WMI for Exception Logging from .NET
Rick Strahl - C# ValueTuple
Patrick Smacchia - C# 11.0 new features: raw string literals
Ian Griffiths - Thread Safe Lazy Initialization Using C# Notes
Ken Dale

Seguimos hablando de problemas que es habitual solucionarlos de una determinada manera, quizás por costumbre, quizás por pereza, o tal vez por desconocimiento de que haya otras formas de hacerlo. En este caso, hablaremos de una necesidad que probablemente habréis tenido alguna vez: transformar un GUID a una cadena de caracteres eliminando los habituales guiones.
Es decir, dado un GUID con el valor 1f5772a6-91ca-4035-8b6d-9676ec6d0eaa
, queremos obtener su representación como cadena de caracteres, pero eliminando los guiones, resultando "1f5772a691ca40358b6d9676ec6d0eaa"
.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Atajo para instanciar tipos anónimos en C# y VB.NET
José María Aguilar - Error 404 cargando páginas Blazor Server con parámetros que contienen un punto
José María Aguilar
.NET Core / .NET
- Cómo corregir una Null Reference Exception
Fernando Escolar - Head and Tail using list patterns in C#
Jiří Činčura - Find total number of ways to reach the n’th stair from the bottom in C#
Dot Net Office - How to modernize a legacy .NET Framework WCF app using CoreWCF and .NET 7
Carlos Pons - Realistic Data Generation in .NET With Bogus
Marko Hrnčić - CSharp dotNET How to remove ASCII Control Characters fast and reduce to ASCII set
Metadataconsulting - Which collection interface to use?
Vladimir Khorikov - Programming SVGs with C#
Khalid Abuhakmeh - Static libraries
Eric Sink - C# 11.0: Generic Math, C# Operators and Static Abstract/Virtual Interface Members
Thomas Claudius Huber - Performance: The Fastest Way to Loop Over an Array in Microsoft .NET
David McCarter - Understanding and Using the ‘Unchecked’ Keyword in C#
Ahmet Burhan Simsek - Using Command Binding in Windows Forms apps to go Cross-Platform
Klaus Loeffelmann - C# Lowering
Steven Giesel - 9 Tips to Reduce WPF App Startup Time
Andrey Slabov - Check If a String Array Contains a Value and Get Index
Code Maze

Ahí van los enlaces recopilados durante una griposa y febril semana pasada. Así que espero que os resulten especialmente interesantes. ;-)
Por si te lo perdiste...
- Detectar la prerenderización en Blazor
José María Aguilar - Cómo crear un traceroute con .NET, paso a paso (y II)
José María Aguilar
.NET Core / .NET
- Announcing .NET Community Toolkit 8.1! Better, faster MVVM source generators, .NET 7 support, and more!
Sergio Pedri - Convert GUIDs to a Shorter Textual Representation and Back
Roland Weigelt - .NET 7 Brings Networking Improvements
Edin Kapic - Understanding PLINQ in .NET
Marco Luzzara - Checking for Overflow in C#
Jeremy Clark - C# 12: Primary Constructors
Steven Giesel - Deconstruction in C#
Patrick Smacchia - Property based testing in C#–Part 2
Bart Wullems

Desde la llegada de ASP.NET Core, hace ya algunos años, muchos hemos echado de menos el filtro [OutputCache]
de ASP.NET MVC "clásico". Aunque el nuevo framework ofrece alternativas interesantes para gestionar la caché tanto en el lado cliente como en el servidor, ninguna aportaba las funcionalidades que este filtro nos ofrecía.
Como recordaréis, a diferencia de las opciones ofrecidas actualmente por ASP.NET Core, como el filtro [ResponseCache]
o el middleware ResponseCaching
, que básicamente se regían por los encabezados presentes en peticiones y respuestas HTTP, el filtro [OutputCache]
es una solución de caché residente exclusivamente en el servidor. En este caso, la decisión de si el resultado a una petición se almacena o no se realiza completamente desde la aplicación, de forma totalmente independiente a encabezados o requisitos procedentes del lado cliente.
En ASP.NET Core 7 este filtro ha vuelto a la vida en forma de middleware, que ofrece sus funcionalidades con dos sabores distintos:
- Con anotaciones aplicables a endpoints implementados con Minimal API.
- Como filtro, aplicable a controladores y acciones MVC.
Echémosles un vistazo.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Crear un traceroute con .NET, paso a paso (I)
José María Aguilar - Cómo personalizar los mensajes de error de conexión en Blazor Server
José María Aguilar
.NET Core / .NET
- No, No, No - Tasks are not threads and they are not for performance!
Steven Giesel - Detecting breaking changes between two versions of a NuGet package at packaging time
Gérald Barré - How to Iterate Over JSON Objects in C#
Code Maze - Deserialize Mastodon User XML RSS feeds with .NET
Khalid Abuhakmeh - LINQ for beginners: pick the right methods!
Davide Bellone - Rebus in .NET - Service Bus Implementation
Phil Broderick - Lazy and once-only C# async initialization
Ian Griffiths - Making an Asynchronous Breakfast in .NET
Assis Zang - 5 new advanced features improving C# 11
Tom Deseyn - Cryptography Implementations in .NET
Alvaro Montoya - Getting rid of warnings with nullable reference types and JSON object models in C#
Maarten Balliauw - Profiling .NET on Linux with BenchmarkDotNet
Adam Sitnik

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Las 10 cosas que más fastidian a los programadores
José María Aguilar - Valores y parámetros en cascada con Blazor
José María Aguilar
.NET Core / .NET
- Understanding Task and ValueTask in C#
Code Maze - Give your strings context with StringSyntaxAttribute
Steven Giesel - ConcurrentBag in C#
Code Maze - Adding NuGet packages when offline
Mark Seemann - Challenge: what does this code print? & The answer
Oren Eini - C# 11 List Patterns - Create compatible types
Gérald Barré - .NET Tips and Tricks & ValueStringBuilder
Steven Giesel - OpenTelemetry in .NET - Basic Usage With Examples
Phil Broderick - ReadOnlySpan<char> and strings
Steven Giesel - How to Use Change Tokens in .NET 7?
Goker Akce - Why tuples in C# are not always a code smell
Dennis Frühauff - Automating Integration Tests using the “Critter Stack”
Jeremy D. Miller - Avoiding Primitive Obsession in .NET
Assis Zang

Ante todo, aprovecharé esta inigualable ocasión para desearos lo mejor para este nuevo año 2023 que se está empezando a dibujar. Espero que tengáis oportunidad de cumplir vuestros proyectos y de disfrutar del camino que os lleve a ellos.
Y para empezar con buen pie, como es habitual, vamos a repasar los 10 artículos más leídos en Variable Not Found durante este 2022 que acaba de terminar.
En septiembre de 1947, Grace Murray Hopper y sus compañeros de la Universidad de Harvard descubrieron, sobre un relé electromagnético de su Mark II, una polilla (en inglés, moth) chamuscada que provocaba que su programa no funcionara correctamente. "No funciona porque aquí hay un bicho", debieron pensar.

Lo primero, aunque llegue algo tarde, aprovecho para desearos unas felices fiestas :)
Y siguiendo con nuestro tema, aunque no está recogido en ninguna RFC ni documento oficial (o al menos no he sido capaz de encontrarlo) el código de error HTTP 509 (Bandwidth Limit Exceeded) suele utilizarse para informar al lado cliente de que la solicitud no puede ser procesada porque el servidor ha sobrepasado el límite de ancho de banda que tenía disponible. Normalmente ocurre cuando el plan del hosting utilizado es insuficiente para manejar el tráfico del sitio web, por lo que debe ser upgradeado para que todo siga funcionando.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo detectar navegadores que no soportan Blazor WebAssembly
José María Aguilar - Crear puntos de ruptura en tiempo de ejecución con .NET
José María Aguilar
.NET Core / .NET
- How to Secure Passwords with BCrypt.NET
Code Maze - Build Your Own Podcast App with .NET 7, Blazor, and .NET MAUI
James Montemagno - Ref-structs are technically obsolete
James Turner - Will ChatGPT replace .NET developers?
David Grace - Delete dotnet bin and obj folders recursively
Steve Smith - Extreme LINQ Performance Boost in .NET 7
Ivan Matec - Generating C# bindings for native libraries by using ChatGPT
Muhammad Azeez - Enhancing the Factory Pattern with C# Attributes
John Patrick Glattetre - Better assertions for your unit tests
Johan Smarius - Microsoft .NET History
Lazie Wouters - Introduction to MVVM Source Generators for C# .NET
Julian Ewers-Peters - Saving Christmas with Functional C#
Simon Painter - IEnumerable in C#
Code Maze - How the heap verification mode helps with debugging heap corruption
Maoni Stephens - C# 11.0: Raw String Literals
Thomas Claudius Huber

Si habéis trabajado algo con Blazor, seguramente sabréis que los componentes escritos en archivos .razor
son traducidos en tiempo de compilación a lenguaje C# y posteriormente compilados como cualquier otra clase de nuestro proyecto.
Por tanto, ¿que impediría que nos saltásemos ese paso y escribiéramos nuestros componentes directamente en C#? Efectivamente, nada ;)
En este post veremos cómo hacerlo.
Pero antes, un disclaimer: apenas existen razones prácticas para implementar componentes visuales usando C#. Usando Razor todo será más sencillo, rápido y tendremos menos riesgo a equivocarnos, así que esa debe ser la opción por defecto. Por tanto, lo que vamos a ver aquí no debéis usarlo salvo en casos justificados (por ejemplo, cuando queráis crear componentes sin UI).

El código de estado HTTP 508 (Loop Detected) indican que el servidor ha finalizado la operación debido a la detección de un bucle infinito mientras procesaba una petición realizada con el valor "infinite" en el encabezado "depth". Este encabezado forma parte de las extensiones HTTP de WebDAV y se usa para realizar operaciones que pueden afectar a un recurso y a todos sus miembros, hasta el nivel de profundidad especificado.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Componentes genéricos (templated components) en Blazor
José María Aguilar - La depuración y las cinco fases del duelo
José María Aguilar
.NET Core / .NET
- Using Roslyn to Power C# SDK Generation from OpenAPI Specifications
Brant Burnett - Introducing Wolverine for Effective Server Side .NET Development
Jeremy D. Miller - Schedule Jobs with Quartz.NET
Code Maze - Moving to .NET 7 MSMQ Alternatives
Irwin Williams - PriorityQueues on .NET 7 and C# 11
Davide Bellone - .NET 7 Networking Improvements
Natalia Kondratyeva - 11 Ways of Making Your C# Harder to Use
Brendan Enrick - Fun with C# and Bingo
Eric King - C# 11: pattern matching and static abstract interfaces
Tom Deseyn - Add All Project to Solution with dotnet CLI
Steve Smith - Answer: What does this code print?
Oren Eini - Creating Multi-Tier Subscriptions using C#
Jonathan Danylko - Task<IDisposable> surprise
Jiří Činčura - Using Procdump to generate dumps on a specific .net core exception
Xiao Dong Zhu - Testing in DotNet
Mark Oliver

Otra de las novedades del flamante C# 11 viene a romper una limitación histórica: la ausencia de tipos genéricos en la definición de atributos.
Hasta esta versión del lenguaje, cuando necesitábamos introducir referencias a tipos de datos en un atributo, debíamos pasar obligatoriamente por el uso de un System.Type
y el verboso operador typeof()
. Además de incómodo, no había forma de limitar los tipos suministrados, dando lugar a errores en tiempo de ejecución que bien podrían haber sido resueltos el compilación con las herramientas apropiadas.
Dicho así quizás sea difícil de entender, pero veámoslo con un ejemplo.

Pasando del 503 ninguno de los códigos de estado HTTP son demasiado conocidos, así que esto se está convirtiendo en una oportunidad para echarles un vistazo y al menos, saber que están ahí.
Esta semana seguimos con el HTTP 507 (Insufficient storage), que indica que el espacio de almacenamiento en el servidor no es suficiente para completar la operación. Según la especificación, la petición no debe ser reintentada hasta que sea solicitada por una acción independiente del usuario; o sea, que cuando recibamos este error, deberíamos informar al usuario y, si procede, permitirle reintentar.
Y ahora, ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo invocar métodos de instancia C# desde Javascript con Blazor (interop 3/3)
José María Aguilar - Formas efectivas de ofuscar emails en páginas web
José María Aguilar
.NET Core / .NET
- A new wave of analyzers in .NET 8
Steven Giesel - C# 11 Strings in the Raw
Shawn Wildermuth - .NET and C# Versions
Niels Rasmussen - Floating-Point Types in C# - Double vs Float vs Decimal
Code Maze - An initial proof of concept of applicative assertions in C#
Mark Seemann - Hashing and Salting Passwords in C# - Best Practices
Diego García - C# Tip: Raise synchronous events using Timer (and not a While loop)
Davide Bellone - Having fun with C# 11 raw string literals
Jiří Činčura - Starting a process as normal user from a process running as Administrator
Gérald Barré - Benchmark Your Code Like dotNetDave!
David McCarter - Introducing C#11: List Pattern
Anthony Giretti - Trying out the built-in container support for the .NET SDK
Carlos Pons - Producer-Consumer Applications With .NET Channels Code Maze
Code Maze - New ArgumentException and ArgumentOutOfRangeException helpers in .NET 8
Steven Giesel

Hace algunas semanas vimos cómo crear inline route constraints, o restricciones de ruta en línea en ASP.NET Core, y creamos un ejemplo simple que permitía al sistema de routing detectar si el valor suministrado a través de un parámetro de ruta era una palabra palíndroma.
Para ello, creamos la restricción "palindrome" que, implementada en la clase PalindromeConstraint
podíamos usar de la siguiente forma:
// Uso en minimal API:
app.MapGet("/test/{str:palindrome}", (string str) => $"{str} is palindrome");
// Uso en MVC:
public class TestController : Controller
{
[HttpGet("/test/{str}")]
public string Text(string str) => $"{str} is palindrome";
}
Sin embargo, si atendemos a la lista de restricciones disponibles de serie en ASP.NET Core, vemos que hay algunas de ellas que son parametrizadas, como maxlength
o range
:
Plantilla de ruta | Significado |
---|---|
/order/{orderId:minlength(5) |
orderId debe tener como mínimo 5 caracteres |
/setAge/{age:int:range(0,120) |
age debe ser un entero entre 0 y 120 |
En este post vamos a ver precisamente eso, cómo crear una restricción personalizada con parámetros.

El desconocido (al menos para mí) código de estado HTTP 506 (Variant also negotiates) indica que el servidor tiene un error de configuración en el contexto de la Negociación Transparente de Resultados (RFC 2295). Permite informar al cliente de que la variante que ha elegido está configurada para participar en la negociación de contenidos, pero no es válida como endpoint para el proceso de negociación-
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo solucionar el error "Unable to connect to web server 'IIS Express'" en Visual Studio
José María Aguilar - Cómo saber si tenemos el debug=true en el Web.config
José María Aguilar
.NET Core / .NET
- .NET 7 Adds Generic Math
Jonathan Allen - Creating Containers in .NET 7 with the .NET CLI
Anuraj Parameswaran - How to get allocations in .NET? And how big is an empty array?
Steven Giesel - Static Abstract Interface Members in C#11
Dirk Strauss - HashSet vs SortedSet in C#
Code Maze - Creating JSON Web Tokens using dotnet user-jwts tool
Anuraj Parameswaran - Tagged Strings in Visual Studio and .NET 7
Jonathan Allen - Killing all child processes when the parent exits (Job Object)
Gérald Barré - Wolverine | Next Generation .NET Command and Message Bus
Jeremy D. Miller - C# List Pattern Examples
Phil Haack - How to Check if a String Ends With a Number in C#
Code Maze - The dangers and gotchas of using scoped services in OptionsBuilder
Andrew Lock - .NET 7 Removes Its Insecure XmlSecureResolver
Jonathan Allen - "Use always a StringBuilder"
Steven Giesel - Towards a Beginner-Friendly DotNet
Matt Eland - How to Create and Publish a NuGet Package with dotnet CLI
Anuraj Parameswaran - Logging to Amazon Cloudwatch with Serilog in .NET
Mukesh Murugan - Frozen collections in .NET 8
Steven Giesel - The new .NET 7.0 IParsable<TSelf> interface
Patrick Smacchia - A Mostly Complete Guide to C# 11’s Final Features
Matthew MacDonald - Sending An Email In C#/.NET
Daniel Collingwood

Hoy va un post cortito, pero que puede venir bien a alguien que esté intentando "trocear" su aplicación en distintos proyectos y se haya encontrado con este problema.
Echemos un vistazo al contenido típico del archivo App.razor
de una aplicación Blazor (Server o WebAssembly, da lo mismo):
<Router AppAssembly="@typeof(Program).Assembly">
...
</Router>
Resulta que el componente Router
escanea durante su inicialización el ensamblado que hayamos indicado en su atributo AppAssembly
, por defecto el ensamblado actual, en busca de componentes que:
- Hayan definido sus rutas mediante directivas
@page
de Razor, - o bien, que tengan su ruta especificada con atributos
[Route]
En cualquiera de los casos, los componentes localizados son añadidos a la tabla de rutas y, por tanto, será posible navegar hacia ellos modificando la ruta del navegador, ya sea programáticamente (usando el servicio NavigationManager
) o bien mediante la pulsación de enlaces o modificación directa en la barra de direcciones.
Hasta aquí, todo correcto. El problema viene cuando las páginas que queremos añadir a la tabla de rutas no están en el ensamblado actual, o se encuentran repartidas en varios ensamblados distintos, por ejemplo en:
- Otros proyectos de la solución
- Ensamblados externos, referenciados directamente
- Paquetes NuGet instalados en el proyecto

Creo que nunca me he topado en persona con este código de error, así que es una buena ocasión para conocer un poco sobre él.
El código HTTP 505 (HTTP Version Not Supported) es retornado por un servidor cuando rechaza o no soporta la versión major de HTTP utilizada en la petición. En este caso, se recomienda que el servidor incluya en la respuesta la descripción del motivo por el que no soporta la versión utilizada, y qué protocolos debería usar en su lugar.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo invocar métodos estáticos C# desde Javascript con Blazor (interop 2/3)
José María Aguilar - Imágenes en cuadros de texto de formularios web
José María Aguilar
.NET Core / .NET
- Null-Coalescing ?? And Null-Coalescing Assignment ??= Operator
Code Maze - Enforcing .NET code style rules at compile time
Daniel Genezini - The Best C# 11 Feature You Don't Need
Matt Eland - My C# array, tuple, delegate declaration dilemma
Jiří Činčura - How to Return null From a Generic Method in C#
Code Maze - Introducing the C# 11 Required Keyword
Matt Eland - My favourite 'recent' LINQ improvements
Mark Heath - How to Use the “Using Static” Feature in C#
Code Maze - Book: C# for Babies
JetBrains - Using Dynamic LINQ With System.Linq.Dynamic.Core Library
Code Maze - C# 11 and .NET 7 Bring Generic Parsing
Jonathan Allen - C# 11 required members
Patrick Smacchia - Protect yourself when deserializing - System.Text.Json
Josef Ottosson - Anonymous test data with AutoFixture
Steven Giesel - Cysharp/MemoryPack: Zero encoding extreme performance binary serializer for C# and Unity.
Yoshifumi Kawai

La llegada de C#11 viene acompañada de un buen número de novedades, algunas de ellas bastante jugosas, como los raw string literals o el nuevo modificador "file" que ya hemos ido viendo por aquí.
En esta ocasión, vamos a echar el vistazo a otra de las novedades que pueden resultar de bastante utilidad en nuestro día a día: los miembros requeridos.

Como vimos hace unas semanas, el código HTTP 502 es usado por gateways, proxies o intermediarios similares para informar al cliente de que la petición al servidor real estaba retornando un error, pero, ¿qué ocurre cuando dicho servidor ni siquiera responde en un tiempo determinado? Pues para eso existe el HTTP 504 (Gateway timeout).
Y ahora, ahí van los enlaces recopilados durante la semana pasada, con muchas novedades y lanzamientos que, como de costumbre, espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿A qué huele tu código?
José María Aguilar - Cómo invocar funciones Javascript desde Blazor (interop)
José María Aguilar
.NET Core / .NET
- .NET 7 is Available Today
Jon Douglas - Welcome to C# 11
Mads Torgersen - Announcing F# 7
Vlad Zarytovskii - Announcing NuGet 6.4 - Signed, Central, Delivered
Jon Douglas - What's new in Windows Forms in .NET 7.0
Igor Velikorossov - What's new for WPF in .NET 7
Pankaj Chaurasia - What's new in Orleans 7.0
Brady Gaster - Mutable value types are evil! Sort of...
Steven Giesel - Top 10 Dotnet Exception Anti-Patterns in C#
Matt Eland - How to Use HTML Agility Pack in C#
Diego García - Debugging tips and tools
Gérald Barré - Tasks vs Threads in C#
Code Maze - Concurrent Processing in .NET 6 with System.Threading.Channels (Bonus: Interval Trees)
Charles Chen - Source Generated RegEx in .NET 7
Steve Collins