
La verdad es que este año me ha dado algo de pereza volver a abrir el blog después de este periodo veraniego de descanso. Aunque disfrute escribiendo y compartiendo información, mantener esto medio vivo requiere esfuerzo y tiempo, que obviamente dejo de dedicar a otras cosas que también me gustan 🙂
Pero bueno, la cuestión es que por aquí andamos de nuevo, listos para inaugurar oficialmente la temporada 2023-2024. ¿Y qué mejor forma de hacerlo que con una nueva recopilación de enlaces interesantes? ¡Pues vamos allá!
Por si te lo perdiste...
- CRUD en Blazor usando el componente DataGrid de Syncfusion
José María Aguilar - Parámetros opcionales: úsense con precaución
José María Aguilar
.NET Core / .NET
- Trazas en .Net
Fernando Escolar - Announcing .NET 8 RC1
Leslie Richardson - Performance Improvements in .NET 8
Stephen Toub - Tales from the .NET Migration Trenches, Empty proxy & Shared library
Jimmy Bogard - Working with API that supports remote streaming using HTTPClient in dotnet
Abdul Rahman Shabeek Mohamed - Building a Resilient Email Sending Method in .NET with SmtpClient, Retry Support, and the Outbox Pattern
Steve Smith - Your Quick Guide to Pattern Matching in C#
Aram Tchekrekjian - Listing Windows virtual desktops using .NET
Gérald Barré - File-Scoped Types in C# 11
Code Maze - Dictionaries in C#: How To Use The Different Variations
Nick Cosentino - Dumb Developer Tricks - Fizz Buzz with C# 12 and Polly
Khalid Abuhakmeh - Creating custom debug visualizers for Visual Studio 2022
Thomas Ardal - Techniques for Checking Floating-Point Equality in C#
Code Maze - The best C# REPL is in your terminal
Anthony Simmon - How to Use Moq to Return a Value That Was Passed Into a Method
Code Maze - Reverse engineering natively-compiled .NET apps
Michal Strehovský - Resilient Http Calls using Polly.
Dhananjeyan Balaretnaraja
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: enlaces

Si sois habituales del blog, probablemente ya sabréis lo que os voy a decir ;)
Como todos los años por estas fechas, empieza el periodo vacacional y aprovecharé para bajar un poco el ritmo, descansar unos días y disfrutar de familia y amigos.
Por tanto, dejaré el blog en modo de bajo consumo hasta bien entrado septiembre, cuando, ya con las pilas recargadas, volveré al ataque con nuevos artículos y enlaces interesantes. Eso sí, durante este periodo seguiré echando el ojo periódicamente a comentarios o mensajes que me dejéis, aunque no los responderé con la misma celeridad que en otras épocas del año.
Aprovecho para desearos a todos un feliz verano y que disfrutéis de las vacaciones. ¡Nos vemos a la vuelta!
Publicado en Variable not found.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Se pueden crear componentes Blazor que no hereden de ComponentBase o alguno de sus descendientes?
José María Aguilar - Consejos imprescindibles por si algo falla
José María Aguilar
.NET Core / .NET
- The minimal API AOT compilation template: Exploring the .NET 8 preview Part 1 & Part 2
Andrew Lock - TimeProvider and ITimer: Writing Unit Tests with Time in .NET 8 Preview 4
Artur Ampilogov - Roslyn Compiler and Analyzers in .NET
Code Maze - Why I like and prefer xUnit
Steven Giesel - Adding a Readme to NuGet Package Landing Pages
Khalid Abuhakmeh - Finding Symbols in Your C# Projects Using Roslyn
Calvin A. Allen - Converting a Byte Array to Hexadecimal String in C#
Code Maze - Customizing Return Value Behavior in Wolverine for Profit and Fun
Jeremy D. Miller - 7 Things about C#: If Statements
Joe Mayo - Discriminated Unions in C# With OneOf
Ryan Miranda - Improved Source Generators and Code Fixers Arrive in .NET Community Toolkit 8.2.1!
Sergio Pedri - Microsoft .NET Code Analysis: UTF-7 Encoding Is Insecure
David McCarter

Por decimotercer año consecutivo, me complace enormemente informaros de que Microsoft ha tenido a bien reconocerme de nuevo como MVP (Most Valuable Professional) en tecnologías de desarrollo. ¡13 años ya, uau! ¡Pero si el primero parece que fue ayer!
Muchas gracias al increíble equipo de Microsoft que hay detrás de este programa por haberme honrado con este reconocimiento, y especialmente a nuestra gran Cristina González por su dedicación, cercanía y ponérnoslo todo tan fácil cuando la necesitamos.
También agradeceros a vosotros, mis queridos amigos, que sois los que con vuestras visitas, lecturas, comentarios y apoyo incondicional hacéis que este sueño siga siendo posible año tras año.
¡Nos vemos por aquí!
Publicado en Variable not found.

Seguro que habéis visto más de una vez un código parecido al siguiente, en el que llamamos a una API REST externa y su resultado es deserializado a un objeto .NET para introducirlo en el flujo de la aplicación:
async Task<User[]> GetUsersAsync()
{
var httpClient = _httpClientFactory.CreateClient();
// Hacemos la llamada
var response = await httpClient.GetAsync("https://jsonplaceholder.typicode.com/users");
// Si la cosa no fue bien, retornamos
if (!response.IsSuccessStatusCode)
return Array.Empty<User>();
// Descargamos la respuesta y la deserializamos
var usersAsJson = await response.Content.ReadAsStringAsync();
var users = JsonSerializer.Deserialize<User[]>(usersAsJson);
return users;
}
Fijaos que el JSON de la respuesta de la API lo guardamos en una cadena de caracteres para, justo después, deserializarlo y convertirlo en un array de objetos User
. Que levante la mano el que no lo haya hecho nunca 😉
¿Y veis dónde está el problema? A la salida de este método, tendremos en memoria dos copias de los datos de los usuarios, una en forma de string
JSON y otra en el objeto que hemos deserializado.
Si estamos hablando de respuestas pequeñas o con poca concurrencia, probablemente el impacto es inapreciable. Pero si las estructuras retornadas por la API tuvieran un tamaño considerable o estamos en un escenario de múltiples llamadas simultáneas, esta duplicidad sería un auténtico derroche de recursos.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Expresiones new con el tipo de destino en C# 9
José María Aguilar - ¿Esa enumeración está vacía?
José María Aguilar
.NET Core / .NET
- El inyector de dependencias de .Net
Fernando Escolar - Consideraciones al publicar un paquete NuGet
Iván Montilla - Missing Stack trace when eliding the await keyword
Steven Giesel - Using the new configuration binder source generator: Exploring the .NET 8 preview
Andrew Lock - Log4net Appenders Introduction With C# Examples
Muhammed Saleem - How to Use Factory Pattern With Dependency Injection in .NET
Ahsan Ullah - 7 Things about C#: Console I/O
Joe Mayo - Microsoft .NET Code Analysis: Always Add Braces in C#
David McCarter - Test Data Generation With AutoFixture in .NET
Code Maze - Rx.NET v6.0: Enhancing Compatibility, Trimming Support, and Many More
Almir Vuk - LINQ: Select.Where or Where.Select?
Steven Giesel - Using Explicit Operators in Microsoft .NET to Perform Type Conversions
David McCarter - How to Hash Passwords with BCrypt in C#
Claudio Bernasconi - Introduction to .NET Releases And Updates
Aram Tchekrekjian - How to Generate C# Business Object Class from a CSV File
Greg Lutz

Cuando en ASP.NET Core MVC usamos rutado por convención, lo habitual es que accedamos a las acciones mediante rutas definidas en el patrón, como [controller]/[action]
. Así, podemos encontrarnos con rutas como /PendingInvoices/ViewAll
para acceder a la siguiente acción:
public class PendingInvoicesController : Controller
{
public IActionResult ViewAll() => Content("Show all pending invoices");
}
Lo mismo ocurre con páginas Razor. Si usamos las rutas por defecto, al archivo /Pages/ShowAllPendingInvoices.cshtml
podríamos acceder mediante la ruta /ShowAllPendingInvoices
. No es que sean rutas terribles, pero tampoco podemos decir que sean lo mejor del mundo en términos de legibilidad y conveniencia.
El kebab-casing consiste en separar con un guion "-" las distintas palabras que componen los fragmentos de la ruta, por lo que en los casos anteriores tendríamos /pending-invoices/view-all
y show-all-pending-invoices
, algo bastante más legible, elegante, y apropiado desde el punto de vista del SEO.
El nombre kebab-casing viene de que visualmente el resultado es similar a un pincho atravesando trozos de comida. Imaginación que no falte 😉
En este post vamos a ver cómo aprovechar los puntos de extensibilidad del sistema de routing de ASP.NET Core para modificar la forma en que genera rutas y así adaptarlo a nuestras necesidades.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Creando gráficas estadísticas en Blazor con los componentes visuales de Syncfusion
José María Aguilar - 30 Leyes epónimas relacionadas con el desarrollo de software (I)
José María Aguilar
.NET Core / .NET
- Introducing the New T4 Command-Line Tool for .NET
Mike Corsaro - Seamless Integration Testing With WireMock.NET
Code Maze - C# 12: Collection literals
Steven Giesel - Wolverine 1.0 is Out! & Wolverine’s Middleware Strategy is a Different Animal
Jeremy D. Miller - Differences Between ExpandoObject, DynamicObject and dynamic
Code Maze - How to use RuntimeHelpers.IsReferenceOrContainsReferences to micro-optimize collections
Gérald Barré - C# Source Code Generators
Bruno Sonnino - C# Struct vs Class: Decoding Key Differences and Use Cases
Wade Gausden - Learn how to mock your HttpClient in C# now with 2 simple methods
Henrique Dalcin Dalmas - Microsoft Forms Service’s Journey to .NET 6
Ray Yao - Validating nested DataAnnotation IOptions recursively with MiniValidation
Andrew Lock - Using StringBuilder To Replace Values
Khalid Abuhakmeh - Parsing websites in C# with Html Agility Pack or AngleSharp
Thomas Ardal - Create your own Mediator (like Mediatr)
Steven Giesel - Getting the .NET Desktop Runtime Installed with a Custom Runtime Checker and Installer
Rick Strahl - Improved .NET Debugging Experience with Source Link
Patrick Smacchia - 7 Things about C#: Running Apps
Joe Mayo - Permutations of a String in C#
Matjaz Prtenjak - Five Reasons Why I Love HangFire
Kevin W. Griffin - Value Objects in C#
Code Maze

Desde la aparición de los nullable reference types, o tipos referencia anulables, en C# 8, nos encontramos frecuentemente con el warning de compilación CS8618, que nos recuerda que las propiedades de tipo referencia definidas como no anulables (es decir, que no pueden contener nulos) deben ser inicializadas obligatoriamente porque de lo contrario contendrán el valor null
, algo que iría en contra de su propia definición.
Para verlo con un ejemplo, consideremos una aplicación de consola con el siguiente código:
var friend = new Friend() {Name = "John", Age = 32};
Console.WriteLine($"Hello, {friend.Name}");
public class Friend
{
public string Name { get; set; }
public int Age { get; set; }
}
La aplicación se ejecutará sin problema, aunque al compilarla obtendremos el warning CS8618:
D:\Projects\ConsoleApp78>dotnet build
MSBuild version 17.4.1+9a89d02ff for .NET
Determining projects to restore...
Restored D:\Projects\ConsoleApp78\ConsoleApp78.csproj (in 80 ms).
D:\Projects\ConsoleApp78\Program.cs(8,19): warning CS8618: Non-nullable property 'Name'
must contain a non-null value when exiting constructor. Consider declaring the
property as nullable.
[...]
[D:\Projects\ConsoleApp78\ConsoleApp78.csproj]
1 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.63
D:\Projects\ConsoleApp78\ConsoleApp78>_
También en Visual Studio podremos ver el subrayado marcando la propiedad como incorrecta:
Aunque muchas veces este warning viene bien porque nos ayudará a evitar errores, hay otras ocasiones en las que puede llegar a ser molesta tanta insistencia. Y en estos casos, ¿cómo podemos librarnos de este aviso?
Disclaimer: algunas de las soluciones mostradas no son especialmente recomendables, o incluso no tienen sentido en la práctica, pero seguro que son útiles para ver características de uso poco habitual en C#.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Crear manualmente instancias de clases usando el proveedor de servicios de .NET
José María Aguilar - PremoniSense, la gran novedad de Visual Studio 2010
José María Aguilar
(¿No era este post una premonición en sí mismo? :D)
.NET Core / .NET
- Announcing .NET 8 Preview 5
Jiachen Jiang - 12: Primary constructor on classes and struct
Anthony Giretti - Optional DependencyInjection in .NET
Federico Alterio - Introduction to Firebase in .NET
Phil Broderick - Collatz sequences by function composition
Mark Seemann - C# Tip: Use custom Equality comparers in Nunit tests
Davide Bellone - How does List work under the hood in .NET?
Steven Giesel - How to detect heap allocations
Bart Wullems

Ya he comentado alguna vez que el hecho de trabajar a diario con C# no implica que conozcamos todas sus funcionalidades, detalles, trampas y recovecos. Después de muchos años, yo sigo encontrándome sorpresas bastante a menudo.
Hace poco, andaba haciendo algunas pruebas y llegué a un código como el siguiente:
var a = 1;
var (b, c) = 4;
var (d, e, f) = 9;
Console.WriteLine(a + b + c + d + e + f ); // Muestra por consola "14"
Así al vistazo, diréis que el código no compila tal cual, pero la pregunta es: ¿sería posible que compilara y, además, mostrara la salida que pretendemos sin tocar una sola línea de las que vemos ahí?
Si lo pensáis un poco seguro que podéis responder a las preguntas. Y si no, pulsad aquí para ver la solución 👇👇
Pues en efecto, el código tal y como está no compila, así que debemos pasar a la siguiente parte de la pregunta: qué podemos hacer para que compile y, además, muestre por consola el valor que buscamos, sin tocar ni una coma de esas cuatro líneas de código propuesto como punto de partida.
Si nos fijamos bien, la primera línea es una asignación normal, pero en la segunda y tercera línea estamos asignando valores a variables usando sintaxis propia de tuplas. En el fondo, ambas líneas son iguales, y fallan en compilación porque no podemos asignar un entero a un tupla. ¿O quizás sí?
Si recordáis, hace mucho tiempo hablamos por aquí de la deconstrucción de clases, un interesante mecanismo que, al más puro estilo de cheff sofisticado, permitía deconstruir o descomponer objetos en tuplas, simplemente implementando el método Deconstruct()
.
Pues bien, resulta que este método Deconstruct()
puede implementarse de forma externa al tipo que va a ser deconstruido mediante extension methods. Seguro que ya empezáis a ver por dónde van los tiros... 😉 En efecto, podríamos implementar el método extensor Deconstruct()
sobre el tipo int
e introducir en él la lógica que nos interese.
Una posible implementación sería la siguiente, en la que tenemos sobrecargas de Deconstruct()
para dos y tres parámetros de salida, entre los que repartimos equitativamente el valor del entero a deconstruir:
public static class IntegerExtensions
{
public static void Deconstruct(this int i, out int i1, out int i2)
{
(i1, i2) = (i / 2, i / 2);
}
public static void Deconstruct(this int i, out int i1, out int i2, out int i3)
{
(i1, i2, i3) = (i / 3, i / 3, i / 3);
}
}
Si ejecutamos ahora mentalmente el código propuesto, veremos que se cumplen los requisitos iniciales:
var a = 1; // a=1
var (b, c) = 4; // "4" se deconstruye en (2,2). Por tanto: b=c=2
var (d, e, f) = 9; // "9" se deconstruye en (3,3,3). Por tanto, d=e=f=3
Console.WriteLine(a + b + c + d + e + f ); //
1+2+2+3+3+3 -> Muestra "14":
Bonito y maquiavélico uso de tuplas y deconstrucción, ¿verdad? 😉

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Indicios de que tu interfaz de usuario fue creado por un programador
José María Aguilar - 3 formas de saber si un componente se está ejecutando en Blazor Server o WebAssembly
José María Aguilar
.NET Core / .NET
- Compartir un fichero C# entre varios proyectos (sin referencias)
Iván Montilla - Time abstraction in .NET 8
Steven Giesel - Where are Objects Allocated in C#? Understanding Heap and Stack
Gevorg Chobanyan - Use secrets in unit tests
Mark Heath - Expression Trees in C#
Code Maze - Enhancing .NET Hot Reload with CreateNewOnMetadataUpdate, MetadataUpdateHandler and MetadataUpdateOriginalType Attributes
Nick Randolph - Refactoring Change Preventers in C#
Code Maze - How to add Dependency Injection, Configurations, and Logging in a .NET 7 Console Application
Davide Bellone - Introducing Sep - Possibly the World's Fastest .NET CSV Parser
Niels Rasmussen - Reduce heap allocations by using static anonymous functions
Bart Wullems - Span / Memory / ReadOnlySequence in C#
Steven Giesel - Managed vs Unmanaged Code (Garbage Collection) in C#
Code Maze - .NET 8: Why .NET 8 preview doesn’t show up in Visual Studio 2022 ?
Anthony Giretti

Hace unos días hablábamos de la serialización polimórfica en .NET 6, y vimos qué posibilidades teníamos para conseguirlo sin tener que escribir un custom converter o conversor personalizado. Y aunque realmente .NET 6 permite hacerlo, no es lo más elegante del mundo porque teníamos que operar sobre tipos object
.
Pero por suerte, en .NET 7 la cosa ha mejorado y ya tenemos opciones razonables para conseguirlo basadas en los dos nuevos atributos [JsonDerivedType]
y [JsonPolymorphic]
. Veamos cómo utilizarlos.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Un vistazo a los patrones relacionales y combinadores, lo nuevo de C# 9 para exprimir el pattern matching
José María Aguilar - El patrón Post-Redirect-Get
José María Aguilar
.NET Core / .NET
- Timers en .Net
Fernando Escolar - nameof get's a bit better in C# 12
Steven Giesel - How to Use SFTP For Secure File Upload in .NET
Code Maze - Getting .NET Library Projects to Output Dependent Assemblies
Rick Strahl - What's the latest .NET roadmap?
Steve Smith - Memory Allocation Optimization With BenchmarkDotNet
Code Maze - How to Convert a String to a Span in C#
Code Maze - Step-by-Step Guide to Adding and Removing Watermarks in PDF using C#
Sameerkhan - New Terminal logger for .NET 8
Steven Giesel - Raiders of the lost root: looking for memory leaks in .NET
Christophe Nasarre - VerificationException in .NET Framework when using structs
Kevin Gosse - .NET 7–Serialize private fields and properties
Bart Wullems - Implicit Operators in C# and How To Create a Multi Type
Nick Cosentino - .NET Micro-Optimization and Refactoring Trick
Patrick Smacchia

Imaginad una clase como la siguiente, que representa las características básicas de los archivos almacenados en una aplicación:
public class File
{
public string FileName { get; set; }
public ulong SizeBytes { get; set; }
}
Y ahora, imaginemos también una clase que hereda de la anterior para modelar específicamente, aunque también de forma resumida, los archivos de vídeo:
public class VideoFile: File
{
public string Codec { get; set; }
public TimeSpan Duration { get; set; }
}
Y puestos a imaginar, acabemos con el siguiente método, que retorna la representación JSON del objeto File
que recibe como parámetro:
string SerializeFile(File file) => JsonSerializer.Serialize(file);
Gracias al polimorfismo, ese pilar imprescindible de la Programación Orientada a Objetos, podríamos invocar este método con objetos de tipo File
, VideoFile
o cualquier descendiente de alguno de ambos, puesto que en todos los casos se trata de objetos de tipo File
:
var file = new File
{
FileName = "file.txt", SizeBytes = 1024
};
Console.WriteLine(SerializeFile(file));
var videoFile = new VideoFile
{
FileName = "video.mp4",
SizeBytes = 1024 * 1024,
Codec = "H264",
Duration = TimeSpan.FromMinutes(3)
};
Console.WriteLine(SerializeFile(videoFile));

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Inicializar a null propiedades sin tipo
José María Aguilar - Cómo saber si un objeto no es nulo (edición C# 9)
José María Aguilar
.NET Core / .NET
- Building a Dynamic Logical Expression Builder in C#
Yohan Malshika - Building Functional .NET Applications: a Guide for Choosing between Nahla Davies
- Detect Globalization-Invariant mode in .NET
Gérald Barré - Understanding the C# Init Operator
Bradley Wells - C# logging: Best practices in 2023 with examples and tools
Shane Duggan - How to Convert Stream to Byte Array in C#
Januarius Njoku - The Ultimate .NET Version Guide
Claudio Bernasconi - How to automatically update a Windows Forms Application?
Renato Ivanescu - .NET 7: Simplify Patch requests with PatchAsJsonAsync extension
Anthony Giretti - 6 useful extensions for IEnumerable
Steven Giesel - Understanding IOptions, IOptionsMonitor, and IOptionsSnapshot in .NET 7
Davide Bellone - Is WPF Dead? - The Current State of WPF [2023]
Claudio Bernasconi - Common C# exceptions and how to fix them
Carlos Schults - How does TryGetNonEnumeratedCount work?
Steven Giesel - How to Generate Permutations in C#
Matjaz Prtenjak - Refactor your .NET HTTP Clients to Typed HTTP Clients
Tim Deschryver - Feature toggle management in .NET Core
Krzysztof Begiedza - .NET Core–Monitor cache misses
Bart Wullems
Hace pocos meses hablábamos de la vuelta del clásico [OutputCache]
en ASP.NET Core 7 y veíamos cómo podía simplificarnos la vida a la hora de cachear en el servidor respuestas de peticiones.
Haciendo un rápido recordatorio, la novedad era la posibilidad de introducir en el pipeline el middleware OutputCacheMiddleware
, que se encargaría de almacenar las respuestas de endpoints y reutilizarlas en posteriores peticiones que cumplieran los requisitos apropiados.

Tras una semana de parón por una semanilla de relax en Roma (ciudad que, por cierto, os recomiendo que visitéis si no lo habéis hecho ya), ahí van los enlaces recopilados durante los últimos días. Como de costumbre, espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Comprometidos o involucrados?
José María Aguilar - Crear bloques de código Razor reutilizables en Blazor con Render Fragments
José María Aguilar
.NET Core / .NET
- Top 5: Errores de performance en C#
Fernando Escolar - Announcing .NET 8 Preview 4
Jon Douglas - Serilog project update, May 2023
Nicholas Blumhardt - Control Visual Studio from an external application
Gérald Barré - Seamlessly Import and Export CSV Data in Excel Using C#
Mohan Chandran - Prevent .NET Application Insights telemetry loss
Anthony Simmon - Exploring Code Performance Testing in C# with BenchmarkDotNet
Kostis Grontis - Why do we need Wait() and Pulse() Methods in C# Threading?
Kulasangar Gowrisangar - Introduction - Rust for C#/.NET Developers
Atif Aziz et al - Upcoming availability of .NET Framework 4.8.1 on Windows Update and Catalog
Brett Lopez - Multidimensional Array vs Jagged Array in C#
Dusko Mirkovic - URI Encode and Decode in .NET
Code Maze - Concurrent Hosted Service Start and Stop in .NET 8
Steve Gordon - Hot Reload Supports Modifying Generics!
Mikelle Rogers - Client Support for Calling WCF/CoreWCF with System.ServiceModel 6.0 Is Here!
Sam Spencer - C# Tip: Advanced Switch Expressions and Switch Statements using filters
Davide Bellone - TaskCompletionSource Pitfalls
Stephan Gay - Struct vs. Record vs. Class in C#
A. Yohan Malshika - An alternative approach to structuring your tests in XUnit
Bart Wullems - Exploring the C# Source Link Feature: Enhancing Debugging Experiences
Neel Bhatt - XML Serialization in C# .NET Core: A Comprehensive Guide
Sanjay M.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo mostrar por consola las líneas que se van añadiendo a logs o archivos de texto, en tiempo real
José María Aguilar - Métodos condicionales en .NET
José María Aguilar
.NET Core / .NET
- C# Record Type: Nondestructive Mutation, Equality, DTOs, and More
Bradley Wells - Verifying your DI Container
Steven Giesel - Reading Windows Application Manifest of an exe in .NET
Gérald Barré - Calling internal ctors in your unit tests”
Phil Haack - Using sizeof() Operator in C#
Code Maze - How to Create a Custom Slack Bot with .NET 7
Daniel Donbavand - How to convert audio to different formats using C# and FFmpeg
Niels Swimberghe - Dot Net Office : Top Microsoft NuGet Packages in 2023
Dot Net Office - Prevent a Hangfire job from running when it is already active
Tim Deschryver - Controlling the log level of your application
Steven Giesel

El 8 de mayo de 2006 decidí subir a un tren, teniendo más o menos clara la dirección, pero sin saber en qué parada me bajaría.
Cuando en aquél post inicial decía literalmente "espero que el viaje sea largo", probablemente no me refería a tan largo. Aún con la tenacidad de la que hacía gala, era imposible imaginar que diecisiete años después seguiría por aquí, contemplando el paisaje y escribiendo sobre lo que veo, intentando contribuir a una comunidad a la que tanto debo.
Más de 1.430 posts, más de 3.000 comentarios de lectores, más de cinco millones de consultas... pero sobre todo, muchísimo aprendido por el camino y, con suerte, espero que no solo por mi parte 😉

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

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