
Hace poco, andaba enfrascado en el proceso de modernización de una aplicación antigua que, entre otras cosas, guardaba datos en formato JSON en un repositorio de archivos. Dado que se trataba de una aplicación creada con .NET "clásico", la serialización y deserialización de estos datos se realizaba utilizando la popular biblioteca Newtonsoft.Json.
Al pasar a versiones modernas de .NET, esta biblioteca ya no es la mejor opción, pues ya el propio framework nos facilita las herramientas necesarias para realizar estas tareas de forma más eficiente mediante los componentes del espacio de nombres System.Text.Json
. Y aquí es donde empiezan a explotar las cosas 😉.
Si habéis trabajado con este tipo de asuntos, probablemente habréis notado que, por defecto, los componentes de deserialización creados por James Newton-King son bastante permisivos y dejan pasar cosas que System.Text.Json
no permite. Por ejemplo, si tenemos una clase .NET con una propiedad de tipo string
y queremos deserializar un valor JSON numérico sobre ella, Newtonsoft.Json
lo hará sin problemas, pero System.Text.Json
nos lanzará una excepción. Esa laxitud de Newtonsoft.Json
es algo que en ocasiones nos puede venir bien, pero en otras puede puede hacer pasar por alto errores en nuestros datos que luego, al ser procesados por componentes de deserialización distintos, podrían ocasionar problemas.
Por ejemplo, observad el siguiente código:
var json = """
{
"Count": "1234"
}
""";
// Deserializamos usando Newtonsoft.Json:
var nsj = Newtonsoft.Json.JsonConvert.DeserializeObject<Data>(json);
Console.WriteLine("Newtonsoft: " + nsj.Count);
// Intentamos deserializar usando System.Text.Json
// y se lanzará una excepción:
var stj = System.Text.Json.JsonSerializer.Deserialize<Data>(json);
Console.WriteLine("System.Text.Json: " + stj.Count);
Console.Read();
// La clase de datos utilizada
record Data(int Count);
Para casos como este, nos vendrá bien conocer qué son los custom converters y cómo podemos utilizarlos.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo saber dónde se está gestionando una petición en ASP.NET Core
José María Aguilar - Inicialización de propiedades en C# 6.0
José María Aguilar
.NET Core / .NET
- .NET 9 Preview 1
Rich Lander - Announcing NuGet 6.9
Allie Barry - Our Vision for .NET 9
.NET Team - Hello, Redis - Getting Started with Redis and dotnet 8
Steve Smith - Garbage Collector (over)simplified & The garbage collector in .NET - Part 2: Compacting
Steven Giesel - Convert Between Hexadecimal and Decimal in C#
Martin Chege - Creating an HttpClient that uses DNS over Https
Gérald Barré - What Is the Difference Between Properties and Fields in C#
Code Maze - LINQ MindMap: .NET 9 Edition
Steven Giesel - Creating custom PowerToys Run plugins
Henrik Lau Eriksson - How to Overwrite DateTime.Now During Testing in .NET
Ivan Gechev - Is Random.GetItems the best way to get random items in C# 12?
Davide Bellone - New Features in C# 12
Bozo Spoljaric - How to Log a Class and Method Names Using Serilog
Muhammad Afzal Qureshi - Enumerating over Select’s index
Jiří Činčura - Weak Events in C# – How to Avoid Nasty Memory Leaks
Nick Cosentino - Polly Core Rate Limiter
Bryan Hogan - An Introduction to the World of Containers with .NET 8
James Montemagno

Como seguramente sabréis, Blazor es la gran apuesta de Microsoft para el desarrollo de aplicaciones web con .NET. Sólo hay que ver la cantidad de novedades que han introducido en la última versión para darse cuenta de que están poniendo toda la carne en el asador y, de alguna forma, está convirtiéndose en la opción preferida para el desarrollo de este tipo de aplicaciones.
Pues bien, es un placer anunciaros que, tras varios meses de preparación, hace unos días hemos puesto en marcha el nuevo curso de desarrollo de aplicaciones Web con Blazor en .NET 8, como siempre, en CampusMVP.
Ha sido un trabajo duro, porque esta última versión ha venida cargada de novedades (sobre todo en lo relativo al nuevo modelo unificado propuesto por las Blazor Web Apps) y hemos tenido que revisar en profundidad y reescribir parte del contenido del curso, rehacer ejemplos y regrabar material audiovisual, todo con el objetivo de seguir siendo el mejor y más completo curso de Blazor del mercado.
En este post voy a intentar responder a las siguientes preguntas:
- ¿Qué es Blazor?
- ¿Por qué es interesante aprender a desarrollar con Blazor?
- Si ya hemos trabajado con ASP.NET Core y MVC, ¿siguen valiendo estos conocimientos?
- ¿En qué consiste el curso de desarrollo con Blazor?
- ¿Cuáles son los contenidos del curso?
- ¿Qué conocimientos previos se necesitan para seguir el curso?
- Me convence, ¿cuándo empezamos?

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Evitar que código de pruebas llegue a producción usando directivas de compilación de C#
José María Aguilar - Ejecutar tareas en segundo plano en ASP.NET 4.5.2
José María Aguilar
.NET Core / .NET
- Volcados de memoria en Kubernetes para depurar aplicaciones .NET
CampusMVP - Enable the new TerminalLogger in .NET 8 SDK automatically
Gérald Barré - How to Correctly Implement IDisposable Interface in C#
Code Maze - General Performance Tip: Optimizing Attributes
David McCarter - Exploring .NET frozen segments
Kevin Gosse - Using default interface methods for performance gains in IHeaderDictionary
Andrew Lock - How to Pass Complex Parameters to Theory in xUnit
Code Maze - How to Get appsettings.json Content as a Dictionary in .NET Core
Code Maze - .NET 8–It’s time to get rid of these flaky tests!
Bart Wullems - Resilience and chaos engineering
Martin Tomka

Hace unos días, veíamos por aquí los constructores primarios de C#, una característica recientemente introducida en el lenguaje que permite omitir el constructor si en éste lo único que hacemos es asignar los valores de sus parámetros a campos de la clase.
Veamos un ejemplo a modo de recordatorio rápido:
// Clase con constructor tradicional
public class Person
{
private readonly string _name;
public Person(string name)
{
_name = name;
}
public override string ToString() => _name;
}
// La misma clase usando el constructor primario:
public class Person(string name)
{
public override string ToString() => name;
}
Como comentamos en el post, los parámetros del constructor primarios eran internamente convertidos en campos privados de la clase, generados automáticamente e inaccesibles desde el código.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Modificar en tiempo de ejecución el valor de los settings de una aplicación ASP.NET Core
José María Aguilar - Eager loading en Entity Framework: mejora drástica del rendimiento en acceso a datos
José María Aguilar
.NET Core / .NET
- Thread.Sleep vs Task.Delay en .NET: cómo introducir retardos en tu código correctamente
José Manuel Alarcón - The fastest way to create WireMock.NET mappings
Cezary Piątek - How to Create XML Files in C#
Matjaz Prtenjak - GetHashCode() in .NET Core
Bart Wullems - Consuming WCF Services in .NET 8 (.NET Core is no more!)
DeeDee Walsh - Tales from the .NET Migration Trenches - Hangfire
Jimmy Bogard - Checking if a collection is empty in C#
Gérald Barré - From Hours to Seconds: The Journey to a 630x Faster Batch Job
Fati Iseni - How to Build a URL Shortener With .NET
Milan Jovanović - Understanding C# 8 default interface methods
Andrew Lock - .NET Tasks, List’s ForEach, and Problems
Khalid Abuhakmeh - How to Select Multiple Records Based on a List of IDs Using LINQ
Bozo Spoljaric - How to Properly Create Message Templates for Logging in C#
Vadzim Zylevich - .NET 8–Refresh memory limit
Bart Wullems - How To Use ArraySegment in C#
Kamil Pakula - Using Azure OpenAI Service to generate images with DALL-E in .NET
Daniel Gomez - HigLabo.Mapper, Creating Fastest Object Mapper in the world with Expression Tree in 10 Days
Higty - Matrix Inverse from Scratch Using SVD Decomposition with C#
James McCaffrey - SearchValues object become better with .NET 9
Steven Giesel

Hace ya algunos años, con la llegada de C# 9, los records nos mostraron otra forma de crear objetos distinta a los clásicos constructores. Ya entonces, y únicamente en aquél ámbito, se comenzó a hablar de primary constructors, pero no ha sido hasta C# 12 cuando se ha implementado de forma completa esta característica en el lenguaje.
En este post vamos a ver de qué se trata, cómo podemos utilizarlos y peculiaridades que hay que tener en cuenta.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- ¿Usar booleanos? ¿Sí, no, a veces?
José María Aguilar - Generar archivos Excel como un señor con ClosedXml
José María Aguilar
.NET Core / .NET
- A Practical Guide to Modular Monoliths with .NET
Charles Chen - How To Remove HTML Tags From a String in C#
Code Maze - Fortifying Your .NET Project
Dick van Straaten - To Upgrade or Not to Upgrade: Is .NET 8 Worth the Leap from .NET 6?
DeeDee Walsh - SerilogTracing
Nicholas Blumhardt - How to get assembly code generated by the JIT for a C# method
Gérald Barré - How to Truncate a String in .NET
Code Maze - How to Escape Curly Brackets and Special Characters in C#
Lennart Pries - A Range kata implementation in C#
Mark Seemann - How to Maximize the Browser Window With Selenium in C#
Semir Teskeredzic - Testing your incremental generator pipeline outputs are cacheable: Creating a source generator
Andrew Lock - C# Tip: ObservableCollection - a data type to intercept changes to the collection
Davide Bellone - How to Check if Items of a List Exist in Another List in C#
Martin Chege - Microsoft Office's RTC (Real-Time Channel) migration to modern .NET
Gilad Oren - Three new LINQ methods in .NET 9
Steven Giesel - Fastest Way to Convert a JObject to a Dictionary in C#
Code Maze

Como sabemos, gran parte de las validaciones en formularios Blazor las implementamos usando anotaciones de datos, o data annotations. Estas anotaciones nos permiten validar los datos de entrada antes de que ejecutemos la lógica de negocio, que normalmente se encontrará en el handler del evento OnValidSubmit
del formulario.
Vemos un ejemplo de formulario Blazor aquí, y el código C# justo debajo:
@page "/friend"
<h3>FriendEditor</h3>
<EditForm Model="Friend" OnValidSubmit="Save">
<DataAnnotationsValidator />
<div class="form-group mb-2">
<label for="name">Name:</label>
<ValidationMessage For="()=>Friend.Name" />
<InputText @bind-Value="Friend.Name" class="form-control" id="name" />
</div>
<div class="form-group mb-2">
<label for="score">Score:</label>
<ValidationMessage For="()=>Friend.Score" />
<InputNumber @bind-Value="Friend.Score" class="form-control" id="score" />
</div>
<div class="form-group mb-2">
<label for="birthDate">BirthDate:</label>
<ValidationMessage For="()=>Friend.BirthDate" />
<InputDate @bind-Value="Friend.BirthDate" class="form-control" id="birthDate" />
</div>
<div class="form-group mb-2">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</EditForm>
@code {
private FriendViewModel Friend = new();
private async Task Save()
{
await Task.Delay(1000);
Friend = new FriendViewModel();
}
public class FriendViewModel
{
[Required(ErrorMessage = "El nombre es obligatorio")]
public string Name { get; set; }
[Range(0, 10, ErrorMessage = "La puntuación debe estar entre {1} y {2}")]
public int Score { get; set; }
public DateTime BirthDate { get; set; }
}
}

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Raw string literals en C# 11
José María Aguilar - Desacoplando controladores ASP.NET MVC, paso a paso
José María Aguilar
.NET Core / .NET
- Avoiding performance pitfalls in incremental generators: Creating a source generator, part 9
Andrew Lock - Authenticating a .NET GitHub App using a JSON Web Token (JWT)
Steve Gordon - An alternative to AutoMapper
Steven Giesel - Difference between CultureInfo.Get and new CultureInfo
Gérald Barré - Converting String to Byte Array in C#
Caleb Okechukwu - Going Native
Cory Smith - How to Save a List to a Text File in C#
Code Maze - What Does yield Do In C#: A Simplified View For Beginners
Nick Cosentino - What We Are Doing Wrong with Logging in C#
Mabrouk Mahdhi - Interceptors – Using C# 12 in Rider and ReSharper
Khalid Abuhakmeh - Mocking GraphQL queries with WireMock.NET
Cezary Piątek - How to Ensure a String Is Valid JSON in C#
Code Maze - 3 Simple Steps to Split an Excel File into Multiple Excel Files in C#
Mohan Chandran - Plugin Architecture Pattern in C#
Alvaro Montoya - How to Create a Temp File in the Temp Folder in C#
Code Maze - A replacement for BinaryFormatter in .NET 8
Steven Giesel

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- PeriodicTimer: Temporizadores asíncronos en .NET 6
José María Aguilar - 101 nuevas citas célebres del mundo de la informática (¡y van 404!)
José María Aguilar
.NET Core / .NET
- GitHub - praeclarum/1brc: The One Billion Row Challenge
Frank A. Krueger - Making primary constructor parameters read-only
Gérald Barré - Consistent Byte Representation of Strings in C# Without Encoding
Code Maze - Throw ThrowIfCancellationRequested in a Method that Returns a Value when Using a Cancellation Token
Bryan Hogan - Coravel - Easy task scheduling for your .NET web apps
Jon Hilton - A brief look at StringValues
Andrew Lock - Const strings are not so const after all
Steven Giesel - Some Stream.Read Guidelines
Mark Heath - Using implicit conversion operators in C# to improve readability
Henrique Dalcin Dalmas - When to Use Thread.Sleep, When to Use Task.Delay?
Code Maze - How to Distribute Roslyn Analyzers via NuGet
Aaron Stannard

Primero, espero que hayáis disfrutado las fiestas y que el 2024 que acabamos de estrenar venga bien cargado de cosas buenas 🙂
Y para inaugurar el año, como cada primer post de enero, aprovecharemos para revisar las diez publicaciones más leídas durante los últimos 365 días.

Ante todo, aprovecho para desearos felices fiestas y, como no nos veremos por aquí hasta enero, un grandioso 2024.
Y, por supuesto, ahí van los enlaces recopilados durante la semana pasada que, como siempre, espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo recibir un JSON como string en una acción ASP.NET Core MVC
José María Aguilar - ¿Por qué separamos los directorios con la barra invertida?
José María Aguilar
.NET Core / .NET
- FluentResults: Simplificando el Manejo de Resultados y Errores en Aplicaciones .NET
Isaac Ojeda - Customize the HttpClient logging
Josef Ottosson - Using the CLI to Build and Run .NET Applications
Dusko Mirkovic - Validating appsettings becomes much faster with .NET 8
David Grace - Custom Naming Policy for JSON in C#
Tomas Bak - Top 6 Performance Tips when dealing with strings in C# 12 and .NET 8
Davide Bellone - Updates to the StronglyTypedId library - simplification, templating, and CodeFixes: Using strongly-typed entity IDs to avoid primitive obsession
Andrew Lock - MemoizR - Declarative Structured Concurrency for C#
Khalid Abuhakmeh - Introduction to Autofac FakeItEasy Package
Ainea Wabwoba - What User Interface Framework Should You Choose for .NET Desktop Applications?
Claudio Bernasconi - Discriminated Unions in C#
Ian Russell - Debugging and Profiling Multithreaded .NET Applications
Code Maze - 5 Serilog Best Practices For Better Structured Logging
Milan Jovanović - What Is String Interpolation In C# – What You Need To Know
Nick Cosentino - What's New in Our Code Coverage Tooling?
Jakub Chocholowicz - The first possible new feature of C# 13: Params collection
Steven Giesel - Execute JavaScript Using Selenium WebDriver in C#
Vadzim Zylevich - Integrating OpenAI Image Generation into a .NET Application
Rick Strahl - A Practical Tour of MoreLINQ
Atif Aziz

Poco a poco vamos haciéndonos con las novedades de C# 12, y en esta ocasión nos centraremos en una nueva sintaxis que proporciona una forma concisa y rápida para declarar los elementos de una colección.
Ya os adelanto que si sois de los que siempre han envidiado otros lenguajes por la facilidad con la que se declaran los elementos de un colección o array, estáis de enhorabuena ;) Porque, sin duda, hay formas de hacerlo menos verbosas que las que hemos tenido hasta ahora en C#:
// JavaScript:
let numbers = [1, 2, 3];
// Python:
numbers = [1, 2, 3]
// PHP:
$array = [1, 2, 3];
// Rust:
let array = [1, 2, 3];
En C# 11 y anteriores, la creación de un array es normalmente más farragosa, porque de alguna forma u otra requiere que especifiquemos que se trata de un nuevo array y, si la inferencia no lo permite, el tipo de los elementos que contendrá:
// Forma verbosa y redundante:
int[] arr1 = new int[3] { 1, 2, 3 };
// Forma clásica, usando 'var' y especificando número y tipo elementos:
var arr2 = new int[3] { 1, 2, 3 };
// Dejamos que el compilador detecte el número de elementos:
var arr3 = new int[] { 1, 2, 3 };
// Dejamos que la inferencia de tipos determine el tipo de los elementos:
var arr4 = new [] { 1, 2, 3 };
// O bien, la más concisa, usando la sintaxis con llaves (sólo válida para arrays):
int[] arr5 = { 1, 2, 3 };

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Archivos JavaScript independientes por componente en Blazor
José María Aguilar - Las 20 mejores tiras cómicas sobre desarrollo de software
José María Aguilar
.NET Core / .NET
- Hardware Intrinsics in .NET 8
Tanner Gooding - Tuple Aliases in C#
Aditi Saxena - Where C# Primary Constructors Make Sense
Steve Smith - A Generic Implementation of Dijkstra’s Smoothsort in C#
Jorge Luis Orejel - 5 Things You Need to Know About Aspire and .NET 8
Growth Acceleration Partners - Redacting sensitive data in logs with Microsoft.Extensions.Compliance.Redaction
Andrew Lock - Hosted service has a major update to its lifecycle events
David Grace - 4 ways to create Unit Tests without Interfaces in C#
Davide Bellone - Build Performance Evaluation Workflow with WorkflowEngine in .NET
Aram Tchekrekjian - How to Decode JWT Tokens in .NET
Muhammad Afzal Qureshi - Generic Type Construction With Static Virtual Interface Members
Brant Burnett - Select a Dropdown Option Using Selenium WebDriver in C#
Semir Teskeredzic - C#– Record types copy constructor
Bart Wullems - All Purpose Object Updater
James Curran

Los records son una interesante fórmula para definir tipos en C# de forma rápida gracias a su concisa sintaxis, además de ofrecer otras ventajas, entre las que destacan la inmutabilidad o la implementación automática de métodos como Equals()
, GetHashCode()
o ToString()
.
Por si no tenéis esto muy fresco, aquí va un ejemplo de record y la clase tradicional equivalente en C#:
// Record:
public record Person(string FirstName, string LastName);
// Clase equivalente (generada automáticamente):
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public override bool Equals(object obj)
{
return obj is Person person &&
FirstName == person.FirstName &&
LastName == person.LastName;
}
public override int GetHashCode()
{
return HashCode.Combine(FirstName, LastName);
}
public Person With(string FirstName = null, string LastName = null)
{
return new Person(FirstName ?? this.FirstName, LastName ?? this.LastName);
}
public void Deconstruct(out string firstName, out string lastName)
{
firstName = this.FirstName;
lastName = this.LastName;
}
}
Como podéis comprobar, hay pocas características de C# que ofrezcan una relación código/funcionalidad tan bárbara como los records. Por ello, poco a poco van ganando popularidad y comenzamos a verlos ya de forma habitual en código propio y ajeno.
Sin embargo, su concisa sintaxis hacen que a veces no sea fácil intuir cómo resolver algunos escenarios que, usando las clases tradicionales, serían triviales.
Por ejemplo, hoy vamos a centrarnos en un escenario muy concreto pero frecuente, cuya solución seguro que veis que puede ser aplicada en otros casos: ya que en los records no definimos propiedades de forma explícita, ¿cómo podríamos aplicarles atributos?

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Llamemos a las cosas por su nombre
José María Aguilar - ASP.NET Core 6, ¿dónde está mi middleware DeveloperExceptionPage?
José María Aguilar
.NET Core / .NET
- .NET 8 Networking Improvements
Máňa & Natalia Kondratyeva - Extending WebAssembly to the Cloud with .NET
Richard Lander - Local Functions in C#
Code Maze - How to Take Advantage of CSharp Optional Parameters for Cleaner Code
Nick Cosentino - How .NET 8.0 boosted JSON Schema performance by 20%
Matthew Adams - Enriching logs with [TagProvider] and ILogEnricher
Andrew Lock - How to use Regular Expressions and Match Evaluators in .NET
Khalid Abuhakmeh - Inline Snapshot testing in .NET
Gérald Barré - Data annotations has some awesome additions in .NET 8
David Grace - Deep C# - Casting the Escape from Strong Typing
Mike James - Learn .NET 8 with New Beginner Videos
Katie Savage - Create Better Looking Console Applications With Spectre.Console
Januarius Njoku - Byte array as a dictionary key? Trying out some options
João Antunes - How to Switch Between .NET SDK Versions
Lennart Pries - .NET Native AOT Explained
NDepend - How to Rename Files in a Folder in C#
Caleb Okechukwu - How to Debug LINQ queries in C#
Michael Shpilt

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo saber si un tipo está registrado en el proveedor de servicios de .NET 6, pero sin necesidad de resolverlo
José María Aguilar - Introducción a SignalR (I): Conceptos básicos
José María Aguilar
.NET Core / .NET
- C# 12: todo lo nuevo del lenguaje aparecido con .NET 8
José Manuel Alarcón - Creating Microsoft Teams Applications with Visual Studio and .NET
Anuraj Parameswaran - How to Check if a File Is in Use With C#
Code Maze - Sep 0.3.0 - Unescape Support (still the Most Efficient .NET CSV Parser)
Niels Rasmussen - 5 Awesome C# Refactoring Tips
Milan Jovanović - Behind [LogProperties] and the new telemetry logging source generator
Andrew Lock - Scriban for Text and Liquid Templating in .NET
Khalid Abuhakmeh - Primary constructors has caused concerns for C# developers
David Grace - Embedding a minimal ASP.NET Web Server into a Desktop Application
Rick Strahl - Building resilient cloud services with .NET 8
Martin Tomka - A journey about the new interceptors of .NET 8
Steven Giesel - TDD and refactoring to patterns in C#: how to write a cron parser
Nicolas Descartes - How to Determine the Operating System in .NET Core
Code Maze - How to make libraries compatible with native AOT
Eric Erhardt - Intercepting HTTP requests with a DelegatingHandler
Tim Deschryver - In Defence of Doubles
Anthony Lloyd

Como sabéis, hasta ahora, los componentes Blazor podían ejecutarse en dos tipos de hosting distintos, Blazor Server y Blazor WebAssembly. Aunque cada uno tiene sus escenarios ideales de uso, ambos enfoques conseguían lo mismo, implementar Single Page Applications en C#, sin necesidad de utilizar JavaScript (bueno, o al menos, minimizando radicalmente su uso):
- Con Blazor Server, se mantiene en el servidor una copia del DOM de cada usuario conectado, de forma que C# puede manipularlo directamente. Luego, mediante una conexión websockets, se sincronizan los cambios con el cliente.
- Blazor WebAssembly lleva al navegador el runtime de .NET, las bibliotecas base y los ensamblados de la aplicación, por lo que todo se ejecuta directamente en el lado cliente gracias a WebAssembly.
Estas dos formas de ejecutar componentes son muy apropiadas cuando se trata de elementos interactivos, capaces de responder a eventos de usuarios y con capacidad de actualizar el contenido de la página. Sin embargo, son muy poco eficientes cuando se trata de páginas estáticas que no requieren interacción con el usuario:
-
Para poder mostrar en el navegador un contenido, en Blazor Server hay que esperar a que el lado cliente descargue la página contenedora, un archivo JavaScript y se establezca la conexión websockets con el servidor, tras lo cual se enviará el contenido de la página.
-
En Blazor WebAssembly, el cliente debe descargar la página contenedora, los ensamblados y todo el entorno de ejecución de .NET y lanzarlo todo sobre WebAssembly. En este momento se puede mostrar el contenido de la página.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Declaración de espacios de nombre en una línea con file-scoped namespaces de C#10
José María Aguilar - Establecer el foco automáticamente en MVC, versión declarativa
José María Aguilar
.NET Core / .NET
- .NET 8: Todas las novedades en 2 minutos
José Manuel Alarcón - Announcing .NET Chiseled Containers
Richard Lander - ConcurrentStack in C#
Code Maze - Find a subset from a set of values whose sum is closest to a specific value–C#
Bart Wullems - Intro to .NET and C# - Differences, Structure, SDK, Runtime...
Code Maze - Embedding additional files in an MSBuild binary log file
Gérald Barré - A failed experiment with interceptors in C# 12 and .NET 8
Andrew Lock - Lo-Fi Service Discovery in .NET8
David Whitney - Fake It Til You Make It...To Production
Martin Taillefer - Validating JSON Against a Schema
Paul Michaels - The Differences Between Quartz.NET and Hangfire
Code Maze - Async Lambda Statements
Bryan Hogan - Primary Constructors – Using C# 12 in Rider and ReSharper
Matthias Koch - How To Harness System.Reactive For The Observer Pattern
Nick Cosentino

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Curiosidad: ¿Por qué el encabezado 'referer' se llama así, y cómo nos afecta a los desarrolladores .NET?
José María Aguilar - ASP.NET MVC: establecer el foco en un control al cargar la página
José María Aguilar
.NET Core / .NET
- Announcing .NET 8
Gaurav Seth - Announcing C# 12
Kathleen Dollard - Announcing F#
Tomáš Grošup - Removing allocations by reducing closure scopes using local variables
Gérald Barré - The Evolution of C#
Aram Tchekrekjian - Optimizing C# code analysis for quicker .NET compilation
Anthony Simmon - Exploring What's New in C# 12
Darren Horrocks - VestPocket: File-based Data Storage for AOT .NET Applications
Khalid Abuhakmeh - How to Use Interceptors in C# 12
Code Maze - A more flexible and enhanced way of logging in .NET 8
Steven Giesel - How to extract, create, and navigate Zip Files in C#
Davide Bellone - C# Interceptors
Paul Michaels - Enums in CSharp – A Simple Guide To Expressive Code
Nick Cosentino - Alias any Type with C# 12
Michael Jolley - Top 10 Must-Have Features in Syncfusion’s C# PDF Library
Sowmiya Loganathan - Standard and Custom Numeric Format Strings in .NET
Code Maze - The CSharp Switch Statement – How To Go From Zero To Hero
Nick Cosentino

Desde su llegada con la versión 7 del lenguaje C#, allá por 2017, nuestro lenguaje favorito dispone de soporte para tuplas. Sin embargo, no he visto muchos proyectos donde estén siendo utilizadas de forma habitual; quizás sea porque pueden hacer el código menos legible, o quizás por desconocimiento, o simplemente porque lo que aportan podemos conseguirlo normalmente de otras formas y preferimos hacerlo como siempre para no sorprender al que venga detrás a tocar nuestro código.
Pero bueno, en cualquier caso, es innegable que las tuplas han venido para quedarse, así que en este post vamos a ver algunos usos posibles, y a veces curiosos, de esta característica del lenguaje C#.

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- El atributo CallerArgumentExpression, o cómo conocer las expresiones usadas como argumentos en llamadas a un método en C#
José María Aguilar - Funciones constructoras en Javascript
Oscar Sotorrío
.NET Core / .NET
- Reading a stream of JsonDocuments separated by new lines (ndjson)
Gérald Barré - Merging Multiple PDFs Using the iText Library
Matjaz Prtenjak - The convenience of System.IO
Richard Lander - Pangram validator in one line
Christian Heilmann - Implementing Distributed Locks in .NET Core with Redis or ZooKeeper
Hamed Salameh - MoonSharp - Running Lua Scripts in .NET
Khalid Abuhakmeh - Updates On Microsoft’s BinaryFormatter Obsoletion Strategy
DevExpress Blogs - Provide opt-in to experimental APIs using C#12 ExperimentalAttribute
Maarten Balliauw - Comparing ForEach Method and Foreach Statement in C#
Code Maze - Let’s build a custom Microsoft Graph connector
Waldek Mastykarz - Read and Write Windows Registry in C#
Code Maze - ConfigureAwait in .NET 8
Stephen Cleary - Discovering The Features Of DotNetFiddle – How To Compile C# Online
Nick Cosentino - .NET Task Parallel Library vs System.Threading.Channels
Charles Chen - TimeProvider makes it easier to mock time in .NET 8
David Grace - Automating Memory Profiling with the JetBrains dotMemory Profiler API
Steve Gordon - Interactive LINQ tutorial, especially for beginners
Steven Giesel