
En código que veo, incluso escrito por mí un tiempo atrás, es muy habitual encontrar comparaciones de cadenas de caracteres en las que, para asegurar que el casing no sea tenido en cuenta, se fuerza una conversión de alguno de los operandos, o incluso ambos, a mayúsculas o minúsculas.
En escenarios muy simples esto funcionará bien y no tendrá contraindicaciones especialmente graves para nuestro sistema. Veamos unos ejemplos:
// Ejemplo 1: conversión de un único operando
int Calculate(string op, int a, int b)
{
// Pasamos a minúsculas el operador para
// asegurar que encaja con la constante
if(op.ToLower()=="add")
{
return a+b;
}
else if(op.ToLower()=="sub")
{
return a-b;
}
...
}
// Ejemplo 2: conversión de ambos operandos
bool AreBrothers(User user1, User user2)
{
// Pasamos a mayúsculas ambos apellidos por
// si alguno se ha escrito usando otro casing
var areBrothers = user1.Surname.ToUpper() == user2.Surname.ToUpper();
return areBrothers;
}
Sin embargo, aunque pueda parecer despreciable, estas operaciones de transformación a mayúsculas o minúsculas tienen un coste importante, que se pone especialmente de manifiesto cuando estamos hablando de aplicaciones con mucha carga de usuarios, alojada en infraestructura muy ajustada o cuando se requiere un rendimiento extremo.
Publicado por José M. Aguilar a las 8:05 a. m.
Etiquetas: .net, nivel básico, optimización

El error HTTP 503 (Service unavailable) lo retornan los servidores para indicar que no están disponibles para responder a la petición. Es habitual encontrarlo al intentar acceder a un sitio web que está en mantenimiento, temporalmente fuera de servicio, o ante un estado de sobrecarga (alta concurrencia, bajos recursos, etc.) El cliente debe interpretarlo como un error temporal, y puede volver a intentarlo de nuevo algo más adelante; para ello, a veces suele acompañarse de un encabezado Retry-After
con la fecha/hora o el número de segundos estimados en los que volverá a estar operativo.
Y ahora, ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo mostrar y ocultar elementos en Blazor
José María Aguilar - 8 curiosidades que quizás no conocías sobre los emoticonos ;-), Parte 1 y Parte 2
José María Aguilar
.NET Core / .NET
- Announcing .NET Community Toolkit v8.1.0 Preview 1
Sergio Pedri - Local functions vs lambda expressions
Steven Giesel - Handling times for an EV charger
Jon Skeet - Deserializing Json Streams using Newtonsoft.Json & System.Text.Json with C# & VB
Graeme_Grant - Advanced LINQ
Alvaro Montoya - Injectio - Source Generator for Dependency Injection
Paul Welter - Encrypt and Decrypt Text Values in .NET
Jamil Hallal - Getting Started With Worker Services
Assis Zang - Just store UTC? Not so fast! Handling Time zones is complicated.
Derek Comartin - Bring WCF apps to the latest .NET with CoreWCF and Upgrade Assistant
Sam Spencer - Marking API's as obsolete or as experimental
Steven Giesel

Primero de todo, va una pildorilla cultural coincidiendo con el número de entrega de la serie de enlaces.
Cuando un servidor HTTP está expuesto a sus clientes a través de un intermediario (proxy, gateway, balanceador o cualquier otro tipo de sistema), es dicho intermediario el que recibe en primera instancia las peticiones, reenviándolas a su destino final y retornando su respuesta. Esto se realiza de forma totalmente transparente para el cliente.
El error HTTP 502 (Bad gateway) es retornado por los servicios intermediarios (proxies, gateways, etc.) cuando no pueden obtener una respuesta válida desde el servidor de destino real de la petición. Por ejemplo, podría ocurrir si éste esté caído, parado por mantenimiento o desconectado de la red, entre otros motivos.
Por si te lo perdiste...
- Cómo personalizar el mensaje "Loading" de las aplicaciones Blazor WebAssembly
José María Aguilar - Cómo describir los elementos de una enumeración usando métodos de extensión y atributos (C# y VB.NET)
José María Aguilar
.NET Core / .NET
- Read CSV File in .NET using CsvHelper
Bradley Wells - Differences between .NET Collection Interfaces
Matt Eland - Automatically version and release .Net Application
Anto Subash - IComparable vs IComparer vs Comparison Delegate
Muhammed Saleem - Dictionary vs Hashtable in C#
Code Maze - The Forgotten Art of C# Inheritance
Szymon Kulec @Scooletz - C# 11 File Scoped Types
Patrick Smacchia - Using WASM and WASI to run .NET 7 on a Raspberry PI Zero 2 W
Laurent Kempé

Modificadores de visibilidad habituales como internal
, public
o private
nos acompañan desde los inicios de C#, permitiéndonos definir desde dónde queremos permitir el acceso a los tipos que definimos en nuestras aplicaciones. Así podemos indicar, por ejemplo, que una clase pueda ser visible sólo a miembros definidos en su mismo ensamblado, que pueda ser utilizada desde cualquier punto, o que un tipo anidado sólo pueda verse desde el interior de su clase contenedora.
Pues bien, C# 11 traerá novedades al respecto ;)
Disclaimer: lo que vamos a ver aquí es válido en la RC2 de .NET 7, pero aún podría sufrir algún cambio para la versión final, prevista para noviembre de 2022.

El error HTTP 501 "Not implemented" se utiliza para indicar al lado cliente que el servidor no soporta las funcionalidades necesarias para poder dar una respuesta a la petición. Puede retornarse acompañado del encabezado Retry-After
para indicar al cliente que puede volver a intentarlo más adelante, cuando estas funcionalidades hayan sido implementadas.
Por ejemplo, la MDN, indica que es la respuesta apropiada cuando el servidor no implementa el método HTTP utilizado en la petición ni para el recurso solicitado ni para cualquier otro. Fijaos que hay una diferencia respecto al error 405, que indica que el recurso está disponible con otro verbo HTTP.
Y ahora, ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Componentes con cuerpo en Blazor
José María Aguilar - Efectos laterales en métodos parciales
José María Aguilar
.NET Core / .NET
- Introducing Spectre.Console
Steve Smith - That Shouldn't Happen - UnreachableException in .NET 7
Abbot - Simplify NuGet Package Versions in your application with Central Package Management
Nick Randolph - Make The First Letter of a String Upper Case in C#
Code Maze - 8 reasons startups prefer Node.js over .NET, and are they justified?
Michael Shpilt - Accessing State in System.Text.Json Custom Converters
Steve Gordon - 3 (and more) ways to set configuration values in .NET
Davide Bellone - Task.ContinueWith implicit type conversion gotcha
Maciej Zwierzchlewski - Common C# Programming Mistakes
Code Maze - Generating Code Coverage Reports in .NET Core
Anuraj Parameswaran - Update on ImageSharp
.NET Foundation - Throwing exceptions - Why is my stack trace lost?
Steven Giesel - Builder Pattern with the implicit operator using
Josef Ottosson

Normalmente, nuestras aplicaciones web ASP.NET Core son hosteadas por aplicaciones de consola, que son las encargadas de crearlas, configurarlas y lanzarlas. Esto suele hacerse mediante una relación de uno a uno: una única aplicación de consola se encarga de gestionar todo el ciclo de vida de una única aplicación web.
Pero, ¿es así necesariamente? En este post veremos que no.

Pues no habría apostado a que llegaríamos tan lejos, pero sí, estamos ante la entrega número 500 de la serie de enlaces interesantes, un post semanal que recoge los mejores contenidos técnicos que voy encontrando por la red, y que me consta que a muchos también os resultan interesantes :)
Ya cuando la serie cumplió diez años publiqué un post respondiendo preguntas que me habéis hecho y seguís haciendo sobre ella, así que si tenéis curiosidad sobre como empezó, el tiempo que dedico a ello o criterios para seleccionar los enlaces, os recomiendo que echéis un vistazo al post, porque todo sigue vigente.
Y ahora, vamos al lío: ahí van los enlaces recopilados durante la semana pasada que, como de costumbre, espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Métodos parciales en C# 3 y VB.NET 9
José María Aguilar - Cómo mostrar el número de usuarios conectados a una aplicación Blazor Server, en tiempo real
José María Aguilar
.NET Core / .NET
- Announcing .NET 7 Release Candidate 2
Jon Douglas & Jeremy Likness & Angelos Petropoulos - Console.ReadKey improvements in .NET 7
Adam Sitnik - Boosting Performance With Sealed Classes in .NET
Marko Hrnčić - Low-level struct improvements in C# 11
Steven Giesel - Calculating MRR with Stripe and C#
Phil Haack - Cursed C# - Doing shenanigans in C#
Steven Giesel - What's new in System.Text.Json in .NET 7
Eirik Tsarpalis & Krzysztof Wicher & Layomi Akinrinade - Modern C# Techniques, Part 3: Generic Code Generation
Stephen Cleary - Functional Programming in C#—A Brief Consideration
Assis Zang - Infographics Compendium II - ThrowHelper, null Task and more
Steven Giesel

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Otras 101 citas célebres del mundo de la informática
José María Aguilar - Capturar todos los parámetros enviados a un componente Blazor
José María Aguilar
.NET Core / .NET
- Adiciones a LINQ en .NET 7.0
Octavio Hernandez - Understanding identity in .NET
Pierre Bouillon - Sorting in C#: OrderBy.OrderBy or OrderBy.ThenBy? What′s more effective and why?
Sergei Vasiliev - Ensuring best practices for NuGet packages
Gérald Barré - Write barrier optimizations in regions
Maoni Stephens - Bending .NET - Compiling 65,536 Programs with Roslyn to Find Valid Identifier Separator char's... then just use
SyntaxFacts.IsValidIdentifier
🤦
Niels Rasmussen - How to build a URL Shortener with C# .NET and Redis
Niels Swimberghe - Bing Ads Campaign Platform – Journey to .NET 6
Mike Treit - Modern C# Techniques, Part 2: Value Records
Stephen Cleary
Las inline route constraints, o restricciones de ruta en línea son un interesante mecanismo de ASP.NET Core para especificar condiciones sobre los parámetros definidos en el interior de los patrones de ruta.
Por ejemplo, una acción MVC o un endpoint mapeado usando el patrón /product/{id}
, será ejecutado cuando entren peticiones hacia las rutas /product/1
y product/xps-15
.
Sin embargo, si en el momento del mapeo utilizamos el patrón /product/{id:int}
estaremos indicando que el manejador sólo debe ser ejecutado cuando el valor del parámetro id
sea un entero.
Esto podemos verlo mejor en un ejemplo. Observad la definición de la siguiente acción MVC, que será ejecutada sólo si el valor para el parámetro id
es un entero, es decir, responderá a peticiones como /product/1
o /product/234
, pero será ignorada si la petición entrante se dirige a la ruta /product/xps-15
:
public class ProductController : Controller
{
...
[HttpGet("product/{id:int}")]
public async Task<ActionResult<Product>> ShowDetails(int id)
{
var product = ... // Obtener producto
return product != null ? product: NotFound();
}
}
O lo que sería su equivalente usando las minimal APIs introducidas en .NET 6:
app.MapGet("/product/{id:int}", async (int id) =>
{
var product = await new ProductCatalog().GetByIdAsync(1); // Obtener producto
return product != null ? Results.Ok(product) : Results.NotFound();
});
Como ya habréis adivinado, en
{id:int}
es donde estamos especificando que el parámetro de rutaid
debe ser entero.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Clases parciales en C# y VB.NET
José María Aguilar - Mostrar HTML "crudo" en componentes Blazor
José María Aguilar
.NET Core / .NET
- Use .NET from any JavaScript app in .NET 7
Pavel Šavara - How to Use Shouldly to Improve Unit Tests in .NET?
Code Maze - Microsoft Commerce's .NET 6 Migration Journey
Kurtis Story - How to generate a dump file of a .NET application
Gérald Barré - The ThreadPool in .NET 7 NativeAOT uses the Windows thread pool
Austin Wise - Introducing C#11: Auto Default structs
Anthony Giretti - Pattern matching is awesome
Steven Giesel - Generate Dynamic PDF Reports from an HTML Template Using C#
Praveen Kumar - Microsoft Teams’ Infrastructure and Azure Communication Services’ Journey to .NET 6
Siavash Fathi & Arman Raina & Bhaskar Bhattacharya - .NET: Learn LINQ as you never have before
Anthony Giretti - x86 vs x64 in .NET
Steven Giesel - By Reference in C#
Peter Ritchie - Modern C# Techniques, Part 1: Curiously Recurring Generic Pattern
Stephen Cleary - Generate Strongly-Typed Resources with .NET Core
Travis Illig - Infographics Compendium I - Generators, pure functions and more
Steven Giesel

En un vídeo del canal de Nick Chapsas, al que por cierto os recomiendo suscribiros, he descubierto que .NET 7 introducirá un mecanismo para "decorar" parámetros, propiedades y miembros de tipo string
de forma que podamos aportar información sobre el tipo de contenido que esperan almacenar.
Para que lo entendáis mejor, observad el siguiente ejemplo, una función que recibe un mensaje y un formato de fecha, y que escribe por consola la fecha actual en el formato indicado seguido del mensaje.
void Log(string message, string dateFormat)
{
Console.WriteLine(DateTime.UtcNow.ToString(dateFormat) + " - " + message);
}
Log("Hello!", "dd/MM/yyyy hh:mm");
Desde el punto de vista del consumidor de la función Log()
, gracias a las ayudas del IDE podremos deducir que el segundo parámetro de tipo string
, llamado dateFormat
, debería ser un formato de fecha válido en .NET. Sin embargo, el entorno de desarrollo no podrá ofrecer ningún tipo de ayuda a la hora de codificar la llamada ni detectar si se producen errores, pues no dispone de información suficiente sobre el tipo de contenido esperado en la cadena de texto que se le suministra.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo conseguir uniones en .Net
José María Aguilar - Blazor Server + Entity Framework Core = InvalidOperationException (si no tienes cuidado)
José María Aguilar
.NET Core / .NET
- C# 11 - Top 5 Features in the new C# Version
Nikola M. Zivkovic - Counting the leading zeroes in a binary number with C#
Andrew Lock - AutoMapper vs Mapster in .NET
Code Maze - Memory is complicated
Steven Giesel - Default interface members and missing “public” in implementation
Jiří Činčura - How to log Correlation IDs in .NET APIs with Serilog
Davide Bellone - Writing unsafe .NET code without the unsafe keyword
Gérald Barré - Enumeration class in C# using records
Josef Ottosson

En algunas ocasiones me he topado con escenarios en los que necesitaba contar, o incluso enumerar, las claves de los elementos presentes en una caché en memoria, inyectada en mis servicios en forma de objeto IMemoryCache
.
Aunque a priori pueda parecer sencillo, esta interfaz no proporciona métodos o propiedades que permitan acceder a la colección que actúa como almacén de los mismos, por lo que nos veremos obligados a usar una estructura de datos adicional (normalmente algún tipo de diccionario o hashset paralelo) para almacenar estos elementos.
¿O quizás tenemos otras fórmulas?
Tras varias semanas de parada, estamos de nuevo al pie del cañón y listos para iniciar la nueva temporada en el blog. Por detrás quedan algunas semanas de descanso, ya totalmente olvidadas, algunos objetivos incumplidos, como mover el blog a WordPress, y otros completados como la actualización de los cursos de ASP.NET Core y Blazor en CampusMVP a las últimas previews de .NET 7, que me ha tenido bastante ocupado.
Y qué mejor forma de volver que publicando la colección de enlaces que he ido recopilando durante la semana pasada, ¿verdad? Pues aquí los tenéis; como siempre, espero que os resulten interesantes.
Por si te lo perdiste...
- Diez años de enlaces interesantes: lo que siempre habéis querido saber sobre esta serie
José María Aguilar - Comentar porciones de código en un archivo .ASPX
José María Aguilar
.NET Core / .NET
- Announcing .NET 7 Release Candidate 1
Jeremy Likness - Working with System.Random and threads safely in .NET Core and .NET Framework
Andrew Lock - Referencing a Local Private NuGet Package in your Solution
Rick Strahl - Performance Improvements in .NET 7
Stephen Toub - .NET now on Windows Package Manager
Ashita Nagar - Serializing asynchronous operations in C#
Raymond Chen - C# Lambda Discards
Ian Griffiths - Improving Unit Tests with Fluent Assertions
Alvaro Montoya - Arm64 Performance Improvements in .NET 7
Kunal Pathak - AutoMapper Madness - Nuances in Self-Mapping
Scott DePouw - .NET One-line Scoped Initializers with Dependency Injection
Khalid Abuhakmeh - C# Tip: use Miniprofiler instead of Stopwatch to profile code performance
Davide Bellone - Microsoft Teams Assignments Service's Journey to .NET 6
Kevin Halverson - How to turn an ASP.NET Core appsettings.json file into a fast-read database
Jon P Smith
Como todos los mediados de Julio, poco más o menos, os informo de que el blog entrará en modo de bajo consumo de energía (de mi energía, básicamente 😉) hasta el próximo mes de septiembre, cuando volveremos a retomar el ritmo habitual de publicaciones.
Mientras tanto, espero descansar un poco, renovar fuerzas y disfrutar de la familia y la buena compañía, que durante el año no siempre es posible prestarles la atención que merecen.
Nos vemos a la vuelta, con las baterías bien cargadas y listos para comenzar la nueva temporada. ¡Que disfrutéis de las vacaciones!

Autor: Guillermo Martínez
Publicado en Variable not found.
Como sabemos, la respuesta a todas las peticiones HTTP comienzan por un código de estado que indica el resultado de la operación. Ahí encontramos desde los códigos más célebres, como HTTP 200 (Ok) o HTTP 404 (Not found) hasta otras joyas menos conocidas como HTTP 429 (Too many requests) o HTTP 418 (I'm a teapot).
Sin embargo, pocas veces nos fijamos en el texto que acompaña al código de respuesta, denominado reason phrase (en los ejemplos anteriores va entre paréntesis, como "Ok" o "Not found"). Según se define en la RFC 7230 sección 3.1.2, la reason phrase...
"... existe con el único propósito de proporcionar una descripción textual asociada con el código de estado numérico, principalmente como una deferencia a los protocolos iniciales de Internet, que eran utilizados frecuentemente por clientes de texto interactivos. Un cliente DEBERÍA ignorar su contenido"
Por tanto, dado que se trata de un texto arbitrario y puramente informativo, deberíamos poder modificarlo a nuestro antojo, más allá de los textos estándar proporcionados por el framework.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- AddMvc(), AddControllers(), AddControllersWithViews(), AddRazorPages()... ¿qué es todo eso?
José María Aguilar - Inicialización rápida de objetos en C# 3.0 y VB.Net 9.0
José María Aguilar
.NET Core / .NET
- ¿Depende el ecosistema de .NET de Microsoft?
Iván Montilla - CoreWCF 1.1.0 and project templates
Sam Spencer - A Practical Guide to Higher Order Functions in C#
Sam Walpole - Async Enumerable in C# (Part 3)
Mark Heath - Finding the maximum value in an array using vectorization
Gérald Barré - Using the new INumber type to generify math functions in .NET 7
Pierre Bouillon - Lightweight Mathematical Permutations Using C#
James McCaffrey - Returning XML from minimal APIs in .NET 6
Andrew Lock - How to solve InvalidOperationException for constructors using HttpClientFactory in C#
Davide Bellone - HttpClient vs RestSharp - Which One to Use in .NET
Code Maze - Low Code Ceremony Sagas with Jasper & Marten
Jeremy D. Miller - Understanding the Stack and Heap in C#
Liam Mooney - Instrumenting .NET with OpenTelemetry
Sly Gryphon - Add an Infinispan cache to your ASP.NET application
Vittorio Rigamonti - Making production diagnostics easier with Source Link
Mark Downie
Un año más, es una alegría enorme compartir con vosotros que Microsoft me ha reconocido por duodécimo año consecutivo como MVP (Most Valuable Professional) en la categoría de tecnologías de desarrollo. Aunque ha pasado bastante tiempo desde que me sorprendiera el mail con el primer nombramiento, sigo recibiéndolo con gran ilusión, el orgullo de seguir formando parte de esta familia y también la responsabilidad de intentar estar a la altura de este honor.
Y como en este mundo hay que entender de dónde y por qué llegan las cosas, no puedo sino haceros llegar mi eterno agradecimiento a todos los que habéis hecho este sueño posible: a los que visitáis de vez en cuando este rinconcillo de la red para obtener o compartir información, porque sois la gasolina que hace que este motor funcione; al equipo del programa MVP, por su incansable trabajo para conseguir que tengamos una gran comunidad de desarrolladores; y, por supuesto, a mis tres niñas, que asumen mis ausencias con la naturalidad de lo que siempre ha sido así.
Aprovecho también para enviar mis felicitaciones a compañeros que continúan siendo MVP (ya sabéis que no es sólo llegar, también mantenerse) y a los que hoy han recibido ese email con una de las mayores alegrías de su vida :)
¡Nos vemos por aquí!
Publicado en Variable not found.
Una de las (muchas) cosas buenas que trajo ASP.NET Core (y .NET Core en general) sin duda ha sido la popularización de la inyección de dependencias y la filosofía de implementación de componentes desacoplados que expone en múltiples puntos.
Esto ha provocado que en nuestras aplicaciones sea ya habitual encontrar secciones de código dedicadas al registro de decenas o centenares de servicios usando los distintos ámbitos disponibles (scoped, singleton o transient). El problema es que esta abundancia de servicios y la asiduidad con la que registramos nuevos componentes o modificamos sus dependencias hace que se nos puedan pasar por alto detalles que pueden hacer que nuestra aplicación falle. Por ejemplo, es fácil que olvidemos registrar algún servicio, o que, por un despiste, inyectemos servicios en componentes registrados con ámbitos incompatibles.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Ojo a los antipatrones
José María Aguilar - Cómo implementar view-models de componentes Blazor en clases code-behind
José María Aguilar
.NET Core / .NET
- Rop.ProxyGenerator: Source Generator to create ProxyClasses
Ramón Ordiales - Async Enumerable in C# (Part 2)
Mark Heath - AlterNats — High Performance .NET
Yoshifumi Kawai - Ternary Operator ? : in C#
Code Maze - Merging concurrent IAsyncEnumerable<T> operations for increased performance
Stefan Schranz - ZString — Zero Allocation StringBuilder for .NET Core and Unity.
Yoshifumi Kawai - How to Use Span in C# to Improve Application Performance
Code Maze - High performance .NET: Building a Redis Clone – skipping strings
Oren Eini - Faster Guid comparisons using Vectors (SIMD) in .NET
Gérald Barré - Using Refit to Consume APIs in C#
Code Maze - Azure AD OAuth client credential flow with custom certificate walk-through
Nicola Delfino - Nondestructive Mutation and Records in C#
Zoran Horvat - Running .NET Core Applications as a Windows Service
Muhammed Saleem - C# vNext - What could come
Steven Giesel - Comparison of FFT Implementations for .NET
Christian Woltering - Challenge: Find the stack smash bug… – answer
Oren Eini - .NET Debugging Tips
Tim Deschryver - Leveraging trimming to make the Microsoft Store faster and reduce its binary size
Sergio Pedri
Como sabemos, ASP.NET Core viene configurado "de serie" para que el middleware que sirve los archivos estáticos (StaticFilesMiddleware
) los obtenga desde la carpeta wwwroot
. Y ya vimos hace bastante tiempo que si preferíamos utilizar otro nombre para guardar estos archivos, podíamos hacerlo con cierta facilidad.
Pero como a partir de ASP.NET Core 6 el nuevo modelo de configuración cambió varias piezas de sitio, es bueno volver a echar un vistazo y ver cómo podríamos hacerlo en las últimas versiones del framework.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Desinstala fácilmente versiones antiguas de .NET Core con "dotnet-core-uninstall"
José María Aguilar - Saber si una cadena está vacía usando métodos de extensión (C#/VB.Net)
José María Aguilar
.NET Core / .NET
- Benchmarking to the Bottom — Iterating Arrays in .NET
Stephen Walsh - Improving .NET host error messages and supportability
Richard Lander - Async Enumerable in C# (Part 1)
Mark Heath - How to Implement Retry Logic in C#
Code Maze - Implement IXmlSerializable in a readonly struct
Fons Sonnemans - C# 11 - Top 5 Features in the new C# Version
Nikola M. Zivkovic - Consuming anonymous types with DiagnosticListener in .NET 6
Andrew Lock - High performance .NET: Building a Redis Clone– the wrong optimization path
Oren Eini - How to Call Generic Method Using Reflection in C#
Ahsan Ullah - How to improve Serilog logging in .NET 6 by using Scopes
Davide Bellone - Wrap Event based functions into awaitable Tasks
Steven Giesel - Observing all HTTP requests in a .NET application
Gérald Barré - Write Test Progress To The Console With NUnit
Dawid Sibiński - Speed Up Logging in .NET 6
David McCarter - Using records when implementing the builder pattern in C#
Josef Ottosson

De casualidad me he topado con un interesante cambio que .NET 5 introdujo en los componentes de serialización y deserialización System.Text.Json
y que, al menos para mí, pasó totalmente desapercibido en su momento. Por eso, he pensado que quizás sea buena idea dejarlo por aquí, por si hay algún despistado más al que pueda resultar útil.
Como seguro sabéis, al usar los componentes de System.Text.Json
para serializar o deserializar una clase, utilizamos el atributo [JsonIgnore]
para marcar las propiedades que queremos que sean ignoradas al convertir desde y hacia JSON.
Por ejemplo, dada la siguiente clase:
class User
{
public int Id { get; set; }
public string Email { get; set; }
[JsonIgnore]
public string Token { get; set; }
}
En ella estamos indicando expresamente que la propiedad Token
debe ser ignorada, por lo que ésta no aparecerá si serializamos un objeto a JSON:
var user = new User { Id = 42, Email = "john@server.com", Token = "ABCDEF"};
Console.WriteLine(JsonSerializer.Serialize(user));
// Result:
{"Id":42,"Email":"john@server.com"}
Y lo mismo ocurre en sentido contrario:
var jsonStr = "{ \"Id\": 42, \"Email\": \"john@server.com\", \"Token\": \"ABCDEF\"}";
var user = JsonSerializer.Deserialize<User>(jsonStr);
// ¡user.Token es nulo aquí!
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- 101 citas célebres del mundo de la informática
José María Aguilar - ¿Usar try/catch es malo para el rendimiento? Spoiler: no, siempre que nada falle
José María Aguilar
.NET Core / .NET
- Announcing .NET 7 Preview 5
Angelos Petropoulos - OneService Journey to .NET 6
Dominic Nguyen - Introduction to Regular Expressions in C#
Code Maze - High performance .NET: Building a Redis Clone–separation of computation & I/O Oren Eini
- The Perils of Combining Multicast Delegates with Tasks in C#
Liam Mooney - (Re) Introducing Jasper as a Command Bus
Jeremy D. Miller - What is the difference between C#, .NET, IL and JIT?
Steven Giesel - Creating, Inspecting and Decompiling the World's (Nearly) Smallest C# Program
Steve Gordon - C# 11 static abstract members
Patrick Smacchia - goto in action - The exception from the rule
Steven Giesel - C#: IEnumerable, yield return, and lazy evaluation
Isaac Lyman - C# Warning Waves Hint at New Keywords in the Future
Jonathan Allen - Clean up some .NET Clutter
Joseph Guadagno - Should I avoid LINQ for performance reasons?
Mark Heath

Visual Studio sigue introduciendo novedades versión tras versión, y es fácil que algunas de ellas nos pasen desapercibidas y tardemos algún tiempo en conocerlas, o incluso en verles la utilidad. Un ejemplo lo tenemos en los breakpoints temporales y dependientes, dos nuevos tipos de puntos de interrupción añadidos en la versión 2022 que pueden venirnos bien a la hora de depurar aplicaciones.
En este post vamos a echarles un vistazo, por si hay algún despistado más que no se haya dado cuenta de estas novedades.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- El gran consejo para crear código mantenible
José María Aguilar - Cambiar el idioma de mensajes del SDK de .NET Core
José María Aguilar
.NET Core / .NET
- Reflection in C#
Code Maze - Runtime C# Code Compilation Revisited for Roslyn
Rick Strahl - Fun: Leaderboard Output Using C# Pattern Matching
Khalid Abuhakmeh - Exchange Online Journey to .NET Core
David Sterling - .NET 7 Preview 5 - Generic Math
Tanner Gooding - How to Mock the File System for Unit Testing in .NET
Code Maze - High performance .NET: Building a Redis Clone–naively & Analysis & Architecture
Oren Eini - Delegate, Action, Func, Lamdba expression
Steve Giesel - The curse of NULL
Stéphane Gay

Las top level statements o instrucciones de nivel superior de C# 9 introdujeron una alternativa muy concisa para implementar los entry points de nuestras aplicaciones. De hecho, en .NET 6 fueron introducidas como la opción por defecto en las plantillas, por lo que, de alguna forma, se nos estaba forzando a utilizarlas en todos los nuevos proyectos.
Y como casi siempre sucede, rápidamente aparecieron numerosos desarrolladores a los que este cambio no les había hecho nada de gracia, y se manifestaron claramente en contra de que esta fuera la opción por defecto. La decisión por parte de los equipos de Visual Studio y .NET, que ya podemos ver si tenemos las últimas actualizaciones instaladas, es dejar que cada desarrollador decida la opción que más le guste.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Programación esotérica
José María Aguilar - Rutado dinámico en ASP.NET Core 3 MVC
José María Aguilar
.NET Core / .NET
- Round-robin DNS support in .NET HttpClient
Gérald Barré - Photino: Open Source for Building Cross-Platform Desktop Apps via .NET Core
Raddevus - Consuming SOAP Services in .NET Core
Simon Timms - Change C# Record Comparison with Source Generators
Khalid Abuhakmeh - 8 things about Records in C# you probably didn't know
Davide Bellone - Using the Decorator Pattern to Auto-Instrument .Net Classes With Otel Tracing
Roni Dover - Securing .NET App Secrets with AWS Secrets Manager
Kurt Feeley - Getting Functional with C#
Charles Chen - Get the most out of Async/Await in C#
Yacoub Massad - Global Using Directives in C#
Code Maze

A veces, desde aplicaciones .NET de consola, escritorio, o incluso ASP.NET Core, puede resultar interesante conectarse con una hoja de Google Sheets para añadir filas de datos.
Hay varias formas de conseguirlo, pero aquí vamos a ver la que creo que es la más sencilla, pues permite evitar parte del engorroso workflow de OAuth y, lo que es mejor, podemos usarla sin necesitar credenciales de usuario desde, por ejemplo, un servidor o un proceso desasistido.
Ojo: las APIs de Google que vamos a ver son gratuitas, pero tienen limitaciones de uso que debéis conocer antes de utilizarlas.
A grandes rasgos, el proceso consta de los siguientes pasos, que seguiremos a lo largo del post:
- Configuración del proyecto y credenciales en Google Developer Console.
- Creación del documento Google Sheet en el que añadiremos las filas.
- Consumo de las APIs de Google para añadir datos.
¡A por ello!
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Métodos de extensión en C#
José María Aguilar - Publicación self-contained y single-file en .NET Core
José María Aguilar
.NET Core / .NET
- Performance: Lambda Expressions, Method Groups, and delegate caching
Gérald Barré - C# Lambdas Part 2, a Few More Complicated Examples
Bryan Hogan - Unusual optimizations; ref foreach and ref returns
Marc Gravell - How to Mock HttpClient with Unit Tests in C#
Code Maze - Get Tweet Engagements Using .NET and C#
Khalid Abuhakmeh - Everything You Need to Know About the .NET MAUI ListView
Jayaleshwari N. - Provide default configuration to your .NET applications
Niels Swimberghe - Mock Asynchronous Methods Using Moq in C#
Code Maze - Debugging NuGet Packages: Understanding Debugging Symbols and Using Source Link
Elisenda Gascon

A veces no es necesario usar lenguajes esotéricos para crear un código que nadie sea capaz de entender a simple vista... de hecho, lo hacemos muy frecuentemente en nuestro día a día 😉. Basta nombrar inapropiadamente unas cuantas variables, acoplar y desacoplar sin criterio o usar una mala indentación para que nuestro código ya venga "ofuscado" de serie, sin usar ninguna herramienta externa.
Sin embargo hay otro nivel de maldad, que consiste en el abuso de la flexibilidad de sintaxis en algunos lenguajes para construir expresiones diabólicamente enrevesadas. Hace poco me topé por casualidad con un buen ejemplo de ello en JavaScript, un código que, a simple vista, es imposible de entender:
// ¿Qué retorna esta expresión?
(_$=($,_=[]+[])=>$?_$($>>+!![],($&+!![])+_):_)(255)
Obviamente, podemos copiarla y pegarla en la consola de nuestro navegador, y rápidamente veremos de qué se trata. Sin embargo, me pareció interesante dedicar unos minutos a intentar comprender el código, así que vamos a ir troceando y refactorizando esta expresión ilegible hasta convertirla en algo que, al menos, podamos digerir.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Sabes 1337?
José María Aguilar - Cómo documentar y generar código cliente de nuestras APIs utilizando Swagger/OpenAPI
José María Aguilar
.NET Core / .NET
- What's new in C# 11
Bill Wagner - Copying a collection: ToList vs ToArray
Gérald Barré - C# Method to Check if a Number is Composite
Jamil Hallal - Coding Faster with dotNetTips Spargine 6: Validating Arguments Made Easy
David McCarter - Central Package Management for .NET Projects
Bartosz Jarmuż - How to open and read XML files in C# .NET 6
Sanjay M. - 3 ways to check the object passed to mocks with Moq in C#
Davide Bellone - PDF Creation Made Easy with Syncfusion Document Processing Libraries
Praveen Kumar - Unity and .NET, what’s next?
Alexandre Mutel & Kristyna Hougaard

Hace unos días, Variable Not Found cumplió dieciséis añitos de vida, una eternidad para este mundo en el que vivimos, donde todo ocurre tan rápido y las cosas cambian a una velocidad de vértigo 😊.
Dieciséis años viviendo algo único. Cada uno de los 1.350 artículos publicados ha sido para mí una increíble oportunidad de mejora y aprendizaje y, con suerte, espero (y confío) haber podido ayudar a alguno de los muchísimos visitantes que durante este periodo han pasado por aquí y me han animado a seguir en la brecha.
Dieciséis años creciendo juntos. Comencé esta aventura con más pelo, mejor vista y bastante menos canas, pero la ilusión de poder escribir sobre lo que me gusta, con el plus de que esto pudiera ser útil para alguien, sigue intacta.
Pero bah, dejémonos de historias sentimentales... como es tradición, veamos cómo ha funcionado el blog durante este año.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Describiendo APIs ASP.NET Core con Swagger
José María Aguilar - 32 técnicas de producción de ideas
José María Aguilar
.NET Core / .NET
- Announcing .NET 7 Preview 4
Jeremy Likness - Regular Expression Improvements in .NET 7
Stephen Toub - Using the when Keyword in C# While Handling Exceptions
Code Maze - C# Tip: Convert ExpandoObjects to IDictionary
Davide Bellone - Configuring the Diagnostics Port for dotnet monitor
Mark Downie - Finding “routes” of all-pairs shortest paths with Floyd-Warshall algorithm in C#
Oleg Karasik - The Azure Cosmos DB Journey to .NET 6
Vinod Sridharan - Raw String Literals In C# 11
Wade Gausden - Serializing a Cookie container in C#
Infinite Loop - Override vs New Polymorphism In C# .NET
Wade Gausden - How to Find All Distinct Elements of a Given Integer Array
Jamil Hallal

Solemos pensar que el punto de entrada de una aplicación .NET, ya sea el método estático Main()
del clásico Program.cs
o el nuevo Program.cs
de .NET 6 que utiliza top level statements, es lo primero que se ejecuta en nuestras aplicaciones, en realidad no es así. Hay vida antes de que nuestra aplicación empiece a correr ;)
Aunque obviamente su utilidad es limitada y no es algo que necesitaremos hacer a menudo (o probablemente nunca), es conveniente saber que existen varias formas de insertar código que se ejecute antes que lo que siempre hemos considerado el entry point de nuestra aplicación, y es lo que veremos en este post.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Qué es Blazor, eso de lo que todo el mundo habla?
José María Aguilar - Cómo reconocer a los buenos desarrolladores
José María Aguilar
.NET Core / .NET
- Set C# Language Version for All the Projects in a Solution
Bartosz Jarmuż - Getting telemetry data from inside or outside a .NET application
Gérald Barré - How to install and test nuget packages locally
Gary Woodfine - Case Study: Double performance in under 30 minutes
Nik Karpinsky - Techniques and tools to update your C# project - Migrating to nullable reference types
Maarten Balliauw - Using HTTPListener to build a HTTP Server in C#
Nick Charlton - Upgrading a WCF service to .NET 6 with CoreWCF
Mike Rousos - Microsoft Graph's Journey to .NET 6
Joao Paiva - Challenge: Spot the optimization & Challenge: Spot the optimization–solution
Oren Eini - Quickly Map Your NuGet Packages to Sources
Erdembayar Yondon - Generating sortable Guids using NewId
Andrew Lock - One step beyond by using .NET Collections to its fullest
Ioannis Kyriakidis - On awaiting a task with a timeout in C#
Raymond Chen - Forcing HttpClient to use IPv4 or IPv6 addresses
Gérald Barré - Hacking C# - Adjustable arrays
Simon Painter
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Recomendarías a tu hijo que se dedicase al mundo del desarrollo de software?
José María Aguilar - Incluir recursos estáticos en una Biblioteca de Clases Razor (RCL)
José María Aguilar
.NET Core / .NET
- Dockerfile para .Net 6
Fernando Escolar - CoreWCF 1.0 has been Released, WCF for .NET Core and .NET 5+
Sam Spencer - C++ For C# Developers: Part 1 – Introduction
Jackson Dunstan - How to generate Fake data in C#?
Karthik Chintala - Annotating your C# code - Migrating to nullable reference types
Maarten Balliauw - Create .NET Objects without Calling The Constructor
Khalid Abuhakmeh - Sharing coding style and Roslyn analyzers across projects
Gérald Barré - Different Ways to Implement IHttpClientFactory in .NET Core Apps
Mahesh More - Using User Secrets Configuration In .NET
Wade Gausden - C#: Add event handlers dynamically using reflection
Mike Hadlow
Imaginad que tenemos un controlador MVC como el siguiente:
public class TestController : Controller
{
public IActionResult Add(int a, int b)
{
return Content($"Result: {a + b}");
}
}
Claramente, la acción Add()
retornará la suma de los enteros a
y b
que le llegarán como parámetros de la query string:
GET https://localhost:7182/test/add?a=1&b=2 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Result: 3
Pero, como sabemos, podríamos llamar a la acción sin indicar alguno de esos parámetros, o incluso ninguno de ellos:
Petición | Respuesta |
---|---|
GET /test/add?a=1&b=2 | Result: 3 |
GET /test/add?a=0&b=0 | Result: 0 |
GET /test/add?a=1 | Result: 1 |
GET /test/add | Result: 0 |
Esto es así porque el binder será capaz de poblar correctamente los parámetros a
y b
cuando estén presentes en la cadena de la petición y sean correctos, o les asignará su valor por defecto (0
) cuando no hayan sido suministrados.
Pero dado que el cero es un valor de entrada válido, a priori desde nuestro código no tendríamos forma de distinguir cuándo el parámetro ha sido omitido y cuándo se ha establecido expresamente.
¿Cómo podríamos hacerlo?
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- 7 Hábitos de personas altamente innovadoras
José María Aguilar - Streaming en gRPC, parte II: Streaming bidireccional
José María Aguilar
.NET Core / .NET
- ¿Se ha vuelto demasiado complejo C#?
Eduard Tomás - Cómo manejar JSON en .NET con System.Text.Json
José Manuel Alarcón - Ejemplo de un método deshonesto en C# .NET y cómo refactorizarlo
Albert Capdevila - C# 11 Preview Updates - Raw string literals, UTF-8 and more!
Kathleen Dollard - A Time-Scoped Registration Mechanism for Microsoft.Extensions.DependencyInjection
David Kröll - Running JavaScript inside a .NET app with JavaScriptEngineSwitcher
Andrew Lock - Internals of C# nullable reference types - Migrating to nullable reference types
Maarten Balliauw - Using dotnet format Command to Format the C#/.NET Code
Ryan Miranda - C# async await explained
Patrick Smacchia - Building a NuGet Packages Architecture Part 6 - Enhancing your packages
Imar Spaanjaars - C# Tip: How to temporarily change the CurrentCulture
Davide Bellone - Async and Async Void Event Handling in WPF
Rick Strahl - C# Code Rules
Christian Findlay - Running and Debugging Multiplatform .NET Core (.NET5 or .NET6) GUI and Console Applications on Windows Subsystem for Linux (WSL)
Nick Polyak

La semana pasada veíamos algunas alternativas para comprobar de forma eficiente si una cadena de texto contiene un JSON válido y, al hilo de dicho post, el amigo Javier Campos aportó vía Twitter una fórmula adicional mejor que las que vimos aquí.
El código en cuestión es el siguiente:
public bool IsJsonWithReader(string maybeJson)
{
try
{
var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(maybeJson));
reader.Read();
reader.Skip();
return true;
}
catch
{
return false;
}
}
La estructura Utf8JsonReader ofrece una API de alto rendimiento para acceder en modo forward-only y read-only al JSON presente en una secuencia de bytes UTF8. Los métodos Read()
y Skip()
se encargan respectivamente de leer el primer token del JSON y saltarse todos sus hijos, con lo que en la práctica se recorrerá el documento completo, lanzándose una excepción en caso de ser inválido.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Streaming en gRPC, parte I: Streaming unidireccional
José María Aguilar - Variables locales implicítamente tipadas en C#
José María Aguilar
.NET Core / .NET
- Announcing .NET 7 Preview 3
Jon Douglas - Nullable reference types in C# - Migrating to nullable reference types
Maarten Balliauw - Getting Disk information in Windows with C#
Bruno Sonnino - Reflected Image in C# with GDI and Unchecked Code
AdventureDriver - .NET Automatic Updates for Server Operating Systems
Jamshed Damkewala - Keeping up with .NET: learning about new features and APIs
Andrew Lock - Adding Alt Text To Twitter Images Using C#
Khalid Abuhakmeh - Warning on lower case type names in C# 11
Jared Parsons - Faster .NET development on Kubernetes with Skaffold
Salvatore Merone - Introducing Central Package Management
Jeff Kluge - Using the Roslyn APIs to Analyse a .NET Solution
Steve Gordon - Deep C# - Interface
Mike James - Discussing alternative memory management strategy for .NET
Mark Pelf - Dissecting AutoMapper Programming Horror
Jimmy Bogard - Ignoring JSON Key Casing and Numbers as Strings when Deserializing with System.Text.Json
Bryan Hogan
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Ojo con la inicialización de propiedades usando expression bodied members
José María Aguilar - 13 Consejos para comentar tu código
José María Aguilar
.NET Core / .NET
- .NET Framework 4.5.2, 4.6, and 4.6.1 will reach End of Support on Apr 26, 2022
Jamshed Damkewala - How to prevent Email HTML injection in C# and .NET
Niels Swimberghe - Implementing OAuth2 Client credentials flow APP to APP security using Azure AD non interactive
Damien Bowden - GDI/User Object Leak Tracking – The Easy Way
Alois Kraus - Creating and Using HTTP Client SDKs in .NET 6
Oleksii Nikiforov - Must-Know Concepts Related to LINQ and IEnumerable
Ioannis Kyriakidis - How segments and regions differ in decommitting memory in the .NET 7 GC
Maoni Stephens - C# Pattern Matching Explained
Patrick Smacchia - C# Tip: Use Debug-Assert to break the debugging flow if a condition fails
Davide Bellone - Value types and exceptions in .NET profiling
Christophe Nasarre - Forcing HttpClient to use IPv4 or IPv6 addresses
Gérald Barré - Challenge: Why is this code broken?
Oren Eini - Speed Up Logging in .NET
David McCarter

Al hilo del post Cómo recibir un JSON como string en una acción ASP.NET Core MVC, el amigo Alberto dejaba una interesante pregunta en los comentarios: ¿y si una vez hemos recibido el string
, queremos validar que sea un JSON válido?
Obviamente, una forma sencilla sería intentar deserializarlo por completo a la clase de destino, siempre que ésta sea conocida. Para ello podríamos utilizar el método Deserialize<T>()
del objeto JsonSerializer
de System.Text.Json
, disponible en todas las versiones modernas de .NET, de la siguiente manera:
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Evitar el postback al pulsar un botón en ASP.Net
José María Aguilar - Implementación de servicios gRPC con ASP.NET Core
José María Aguilar
.NET Core / .NET
- What’s up with TimeZoneInfo on .NET 6? (Part 2)
Jon Skeet - Using PowerPoint as a WYSIWIG Editor for HTML Templates (Proof of Concept in C#)
Roland Weigelt - Search videos through the YouTube Data API from C#
Thomas Ardal - Converting code to the new Regex Source Generator
Gérald Barré - Tracking down a hanging xUnit test in CI: building a custom Test Framework
Andrew Lock
A veces, sobre todo en aplicaciones muy grandes, con las definiciones de rutas muy complejas o cuando nos toca analizar aplicaciones ajenas, puede ser interesante saber qué punto del código está procesando una petición determinada, ya sea un endpoint definido usando Endpoint Routing o Minimal APIs o bien sea una acción de un controlador MVC.
En este post vamos a ver cómo conseguirlo de forma muy sencilla, mediante la implementación un pequeño middleware que, insertado en el pipeline, añadirá en el encabezado información sobre el handler que generó la respuesta de la petición actual.