Los que llevamos muchos años programando con ASP.NET/ASP.NET Core y todos los frameworks que han ido surgiendo en su ecosistema, estamos familiarizados con el concepto de "contexto HTTP".
Materializado en forma de objeto de tipo HttpContext
, el contexto HTTP es una de las piezas fundamentales de la infraestructura de ASP.NET Core, y nos permite acceder a información sobre la petición HTTP que se está procesando, como los encabezados, el cuerpo de la petición, las cookies, etc., así como base para la generación de la propia respuesta a través de su propiedad Response
. En muchos escenarios, se trata de un recurso imprescindible para procesar la petición de la forma adecuada, por lo que estamos acostumbrados a usarlo cuando es conveniente.
Sin embargo, cuando saltamos a Blazor, pronto nos llama la atención que HttpContext
no está disponible. Y si lo pensamos, esto tiene bastante sentido en los dos modos de renderización clásicos:
-
En Blazor WebAssembly, dado que el código .NET se ejecuta directamente en el cliente, no existen peticiones que procesar y, por tanto, no existe
HttpContext
. Se trata de una abstracción que sólo existe en el backend. -
En Blazor Server, aunque el código se está ejecutando en el servidor, tampoco tenemos disponible
HttpContext
porque realmente no existen peticiones: el lado cliente y servidor se comunican mediante un canal websockets implementado con SignalR, que es por donde viajan ascendentemente las acciones realizadas por el usuario y descendentemente las actualizaciones del DOM de la página.
Con la llegada de Blazor 8, ha tomado relevancia el nuevo modo de renderizado, llamado Server-Side Rendering (SSR) o renderización en el lado servidor, que ya vimos por aquí hace algún tiempo.
Como ya sabemos, el funcionamiento de Blazor SSR es similar al de otros frameworks de backend puros, como MVC o Razor Pages: el servidor recibe la petición, la procesa y genera una respuesta HTML que se envía al cliente. En este escenario, durante el proceso del componente Blazor sí existe un contexto HTTP.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Requerir parámetros de la query string en ASP.NET Core
José María Aguilar - Rendimiento de nameof en C#
José María Aguilar
.NET Core / .NET
- Key derivation in .NET using HKDF
Anthony Simmon - An introduction to the heap data structure and .NET's priority queue
Andrew Lock - How To Use Polly In C#: Easily Handle Faults And Retries
Nick Cosentino - ConfigureAwaitOptions in .NET 8
Bart Wullems - Introduction to Brighter in .NET
Code Maze - Unveiling Spargine 8: A Comprehensive Guide to .NET 8 Integration and Exciting Feature Updates
David McCarter - Implicit Operators in C#: How To Simplify Type Conversions
Nick Cosentino - Optional parameters may appear in the middle of the parameter list
Gérald Barré - From SerilogTimings to SerilogTracing
Nicholas Blumhardt - Read a Text File Without Specifying the Full Path in C#
Aneta Muslic - Typesafety in xUnit with TheoryData<T>
Steven Giesel - Using parameters in BenchmarkDotNet
Bart Wullems - Extract Method Refactoring Technique in C# – What You Need To Know
Nick Cosentino - Stop Using string.ToLowerInvariant() to Compare Strings. InvariantCulture Comparisons are Slow
Darren Horrocks - Difference Between Abstraction and Encapsulation in C#
Almir Tihak - General Performance Tip: Hashing Data
David McCarter - R3 — A New Modern Reimplementation of Reactive Extensions for C#
Yoshifumi Kawai
En Blazor es posible acceder a valores de parámetros de la query string exclusivamente desde componentes de tipo página, es decir, aquellos definidos con la directiva @page
.
Para ello, bastaba con declarar una propiedad pública y decorarla con los atributos [Parameter]
y [SupplyParameterFromQuery]
. Por ejemplo, si desde una página quisiésemos obtener el valor del parámetro term
de la query string, podríamos hacerlo de la siguiente forma:
@page "/search"
<p>Searching term: @Term</p>
@code {
[Parameter]
[SupplyParameterFromQuery]
public string Term { get; set; }
}
Sin embargo, como sabéis, esto no funcionaba si intentábamos acceder así a estos parámetros desde componentes que no fueran páginas, es decir, que no fueran instanciados por el sistema de routing.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Una forma más eficiente de comprobar si un texto es un JSON válido
José María Aguilar - El operador nameof de C# 6
José María Aguilar
.NET Core / .NET
- String Performance: Comparing Strings with Globalization
David McCarter - A C# LINQ one-liner to check if exactly one of a set of conditions is met
Raymond Chen - Testing exceptions
Mark Seemann - Parallel.ForEachAsync and Exceptions
Jeremy Clark - C# Tip: IFormattable interface, to define different string formats for the same object
Davide Bellone - Reflection in C#: 4 Simple But Powerful Code Examples
Nick Cosentino - Lock statement patterns
Steven Giesel - async await in C#: 3 Beginner Tips You Need to Know
Nick Cosentino - MoaidHathot/Dumpify: Adding
.Dump()
extension methods to Console Applications, similar to LinqPad's.
Moaid Hathot - Continue Processing with Parallel.ForEachAsync (even when exceptions are thrown)
Jeremy Clark - Mocking authorization tokens with WireMock.NET
Cezary Piątek - Activator.CreateInstance in C# – A Quick Rundown
Nick Cosentino
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Verificar si una cadena de texto es un JSON válido
José María Aguilar - Uso de miembros estáticos en C# 6, ¿una buena idea?
José María Aguilar
.NET Core / .NET
- How to Check if a Number Is Positive or Negative in C#
Code Maze - Developing Optimized GitHub Actions with .NET and Native AOT
David Pine - Getting all exceptions thrown from Parallel.ForEachAsync
Gérald Barré - C# System.Text.Json
Karen Payne - How to Get the Number of Lines in a Text File in C#
Karthikeyan N. S. - A Detailed Guide to String Concatenation in .NET
Aleksei - The case for an application-level tracing API in .NET
Nicholas Blumhardt - WinForms in a 64-Bit world - our strategy going forward
Klaus Loeffelmann - AddConsole is obsolete: This method is retained only for compatibility
Bart Wullems - C# for Beginners – 5 Simplified Concepts in C#
Nick Cosentino - .NET JsonElement Error Handling
Ian Griffiths
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.