Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

19 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
lunes, 28 de marzo de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 22 de marzo de 2022
.NET

Aunque no es algo frecuente ni especialmente recomendable, hay veces que tenemos que introducir en el código algún tipo de lógica, trazas o comprobaciones que solo queremos aplicar mientras depuramos o desarrollamos y, en ningún caso, queremos que vaya a producción.

En estos casos, aparte de anudarnos un lazo en el dedo mientras mantengamos estos cambios para asegurar la eliminación del código de pruebas antes de subir la aplicación a producción, otra idea puede ser utilizar directivas para que este código solo actúe mientras depuramos, o incluso para evitar la compilación exitosa en modo "Release" (el usado normalmente al publicar).

lunes, 21 de marzo de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 15 de marzo de 2022
ASP.NET Core

En los tiempos de ASP.NET "clásico", cuando los settings de la aplicación los almacenábamos en el viejo Web.config, cualquier intento de cambio de valores mientras ejecutábamos la aplicación era inevitablemente sinónimo de reinicio. Esto, aunque bastante molesto, tenía sentido porque el mismo archivo XML se utilizaba para almacenar tanto los valores de configuración "de negocio" como aspectos puramente técnicos o del comportamiento de la infraestructura de ASP.NET, y la aplicación debía reiniciarse para poder aplicarlos.

Con la llegada del sistema de settings de .NET Core esto mejoró bastante, introduciendo la posibilidad de almacenar valores en bastantes orígenes distintos (archivos .json, .ini, .xml, variables de entorno, parámetros de línea de comandos, user secrets, diccionarios en memoria y muchos otros, incluso totalmente personalizados), y nuevas fórmulas para la obtención de éstos, como la inyección de dependencias, settings tipados y, por fin, la posibilidad de realizar cambios en caliente.

lunes, 14 de marzo de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 8 de marzo de 2022
Programación No podemos negar que el tipo de datos boolean está fuertemente arraigado en los desarrolladores. Desde nuestros inicios en este mundillo, nos acostumbramos a pensar que las máquinas sólo entienden de unos y ceros o sus variantes humanas: "sí" y "no", "verdadero" y "falso" o similares. Y por alguna misteriosa razón, tendemos a ver la realidad y modelar nuestras soluciones utilizando estas primitivas tan básicas.

Pero aunque indudablemente los tipos booleanos o flags son una fórmula muy compacta para almacenar información, el mundo suele ser mucho más complejo y estas simplificaciones son a menudo origen de problemas y trampas para nuestro yo del futuro.

En este post vamos a ver algunos escenarios en los que este tipo de dato puede llegar a complicarnos la vida.

lunes, 7 de marzo de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 28 de febrero de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 22 de febrero de 2022
.NET

Aún no hemos terminado de asimilar las novedades de C# 10, cuando ya empiezan a llegar noticias de lo que encontraremos en la próxima versión, C# 11, que si todo va bien se lanzará en noviembre de este año.

Una de las que más me ha llamado la atención de momento es la llegada de raw string literals, una característica que mejorará bastante la posibilidad de escribir constantes de cadena multilínea en nuestro código.

Veamos en qué consiste.

Disclaimer: la nueva versión de C# está aún en desarrollo, y detalles de los que veamos aquí podrían cambiar antes de lanzarse definitivamente.
lunes, 21 de febrero de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 15 de febrero de 2022
.NET

Seguimos descubriendo novedades aparecidas con .NET 6, y ahora le toca el turno a la nueva clase PeriodicTimer, una fórmula para la ejecución de tareas periódicas en contextos asíncronos que evita el uso de los clásicos callbacks a los que nos tenía acostumbrados el framework.

Como recordaréis, .NET dispone de un buen número de formas de implementar temporizadores, o timers, para ejecutar tareas en intervalos periódicos. El más conocido probablemente sea el clásico System.Threading.Timer, en el que especificábamos el callback o método que debía ejecutarse en cada intervalo de tiempo mediante un delegado (en el siguiente ejemplo, mediante una lambda):

var timer = new System.Threading.Timer(o =>
{
    Console.WriteLine("Hey! " + DateTime.Now.ToLongTimeString());
}, null, 0, 1000);

Console.ReadKey();
Hey! 12:25:51
Hey! 12:25:52
Hey! 12:25:53
Hey! 12:25:54
Hey! 12:25:55
_

Pero también existía System.Timers.Timer, que nos permitía lograr algo parecido, aunque esta el callback lo implementábamos mediante una suscripción al evento Elapsed del objeto:

var timer = new System.Timers.Timer(1000);
timer.Elapsed += (sender, eventArgs) =>
{
    Console.WriteLine("Hey! " + DateTime.Now.ToLongTimeString());
};
timer.Start();
Console.ReadKey();

Existían algunas fórmulas más específicas para plataformas concretas, como las clases System.Windows.Forms.Timer, System.Web.UI.Timer u otras. Sin embargo, todas coincidían en varias cosas:

  • Utilizaban callbacks de alguna u otra forma, lo que implica un cierto riesgo de leaks de memoria y problemas con los tiempos de vida de objetos cuando la cosa se complica.
  • Los callbacks no permitían código asíncrono, lo que podía llevarnos a luchar contra los engorrosos escenarios de ejecución de código asíncrono en entornos síncronos (async-over-sync).
  • Podían darse casos de superposición u overlapping entre las distintas ejecuciones, cuando éstas tardaban en completarse más que el intervalo de definido en el timer.
lunes, 14 de febrero de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 8 de febrero de 2022
ASP.NET Core MVC

Dada una petición como la siguiente:

POST https://localhost:5001/friends HTTP/1.1
Host: localhost:5001
Content-Type: application/json

{ "name": "Jon", "age": 24 }

Lo habitual es que queramos recibir los datos ya materializados en forma de objeto de .NET. Esto podemos conseguirlo fácilmente desde una acción como la siguiente:

[Route("friends")]
public class FriendsController : Controller
{
    [HttpPost]
    public ActionResult Test([FromBody]Friend friend)
    {
        return Content($"Hello, {friend.Name}, you are {friend.Age} years old");
    }
}

Pero aunque no es algo que ocurra con frecuencia, a veces podríamos necesitar recibir el cuerpo JSON de una petición como string, es decir, en crudo, sin deserializarlo ni procesarlo de ninguna manera para, ya más adelante, hacerlo nosotros manualmente. Y aunque a primera vista pudiera resultar trivial, tiene un poco más de truco de lo que parece...

lunes, 7 de febrero de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 1 de febrero de 2022
Blazor

Si habéis utilizado isolation con módulos JavaScript en Blazor 5, probablemente lo que vamos a ver en este post os resulte muy interesante para organizar los archivos JavaScript de la aplicación, especialmente aquellos que sean utilizados desde un único componente.

Como recordaréis, el aislamiento de JavaScript de Blazor permitía cargar de forma dinámica un archivo .js y ejecutar código definido en él. Por ejemplo, imaginad un módulo como el siguiente, definido en wwwroot/modules/MyPrompt.js:

export function showPrompt(message, defaultValue) {
    return prompt(message, defaultValue);
}

lunes, 31 de enero de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 25 de enero de 2022
ASP.NET Core

El middleware de gestión de errores DeveloperExceptionPageMiddleware ha estado con nosotros desde la llegada de .NET Core, allá por 2016, ayudándonos a mostrar información detallada de las excepciones producidas en tiempo de ejecución mientras estábamos desarrollando. De hecho, era frecuente encontrar un código como el siguiente en las clases Startup de las aplicaciones ASP.NET Core, pues se incluía por defecto en todas las plantillas de proyecto de este tipo:

...
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    ... // Otros middlewares
}

El extensor UseDeveloperExceptionPage() era el encargado de añadir el middleware DeveloperExceptionPageMiddleware al pipeline, de forma que éste podía capturar las excepciones y mostrar una página amigable y con información útil para los desarrolladores.

Sin embargo, si echamos un vistazo al código de configuración del pipeline en los proyectos ASP.NET Core 6 (que, por cierto, sabréis que ya no se encuentra en Startup.cs sino en Program.cs), vemos que ya no aparece ninguna referencia a este middleware. ¿Qué ha pasado? ¿Qué has hecho con nuestro DeveloperExceptionPage, ASP.NET Core 6?

lunes, 24 de enero de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 18 de enero de 2022
.NET

Versiones de .NET anteriores a la 6 no disponían de una fórmula específica para determinar si un tipo o interfaz está registrado como servicio en el sistema de inyección de dependencias.

La única forma de hacerlo era intentar resolverlo, usando métodos como GetService() o GetService<T>(), y comprobar si el resultado era null:

var myService = serviceProvider.GetService<IMyService>();
if(myService is null)
{
    // El servicio no está registrado, hacemos algo
}

¿Cuál es el inconveniente de esto? Si el servicio no está registrado, ninguno: la llamada retornará un nulo y listo. 

El problema viene cuando sí está registrado, pues estaremos forzando la resolución de un servicio que, en realidad, no necesitamos para nada, pues sólo nos interesaba saber si existía o no. Porque recordemos que la resolución de un servicio podría tener un coste importante en términos de rendimiento, memoria, o incluso efectos colaterales en el estado de la aplicación, especialmente si nuestro servicio depende de otros, que a su vez dependen de otros, etc.

lunes, 17 de enero de 2022
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 11 de enero de 2022
Enlaces interesantes

Vamos con la primera colección del año :) Aquí van los enlaces recopilados durante estas fiestas que, como de costumbre, espero que os resulten interesantes.

Por si te lo perdiste...

.NET Core / .NET

lunes, 10 de enero de 2022
Top ten 2020 en Variable not found

Pues parece que comenzamos 2022 con deseos bastante parecidos a los que ya teníamos un año atrás: que la situación actual mejore y que la salud os permita ser felices y disfrutar de todo lo que os rodea. Algo hemos avanzado respecto al año pasado, pero aún nos queda mucho camino por recorrer para volver a la ansiada normalidad.

Pero bueno, independientemente de esto, seguro que lo que más estáis esperando en este momento es el tradicional post donde comentaremos las entradas más visitadas durante el pasado año, así que ahí va 😁

martes, 28 de diciembre de 2021
NET

Hace ya mucho tiempo que C# inició un interesante camino para conseguir reducir la cantidad de código necesario para hacer cosas frecuentes, introduciendo la capacidad de hacer implícitas determinadas construcciones y, por tanto, ahorrándonos tiempo y pulsaciones de teclas innecesarias.

En esta línea, todos recordaréis el tipado implícito, que tanto debate abrió en el lanzamiento de C# 3, hace ya casi quince años:

// Antes de C# 3
List<string> strings = new List<string>();

// Usando tipado implícito
var strings = new List<string>();

Bastante tiempo después, ya con C# 10, el lenguaje nos regaló una nueva característica que iba en la misma dirección, las expresiones new con el tipo destino. Éstas permitían construir objetos usando tipado implícito, aunque esta vez en el lado derecho de las expresiones:

// Antes de C# 10
public class MyClass
{
    private Invoice invoice = new Invoice(123);
    private Dictionary<string, Person> people = new Dictionary<string, Person>();
    ...
}

// Ahora
public class MyClass
{
    private Invoice invoice = new (123);
    private Dictionary<string, Person> people = new ();
    ...
}

También en C# 10 nos hemos encontrado con los using globales y using implícitos, características ambas que nos permiten economizar esfuerzos evitando la introducción repetitiva de directivas para la importación de namespaces en el código.

Pues bien, aquí viene la siguiente vuelta de tuerca :) Unas semanas atrás, Immo Landwerth (Program manager de .NET en Microsoft) sorprendía a todos con esta afirmación sobre una de las características principales del próximo C# 11:

Immo Landwerth announcing implicit dots

lunes, 27 de diciembre de 2021
Enlaces interesantes

Ante todo, espero que estés pasando unas muy felices fiestas y con buena salud, a pesar de las circunstancias complicadas que nos rodean. Espero que pronto podamos salir de todo esto y volver a la normalidad.

Y mientras tanto, os paso algunos enlaces recopilados durante la semana pasada, que espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 21 de diciembre de 2021
.NET

Parece que uno de los objetivos de C#10 es eliminar código de los archivos de código fuente de C#, simplificando su codificación y lectura. Lo hemos visto con la introducción de características como directivas using globales o los using implícitos: en ambos casos se ahorraba espacio en vertical sustituyendo los using declarados individualmente en cada archivo por directivas aplicadas de forma global al proyecto, bien de forma explícita o implícita.

En cambio, los espacios de nombre con ámbito de archivo o namespace declarations permiten ahorrar espacio en horizontal, evitando un nivel de indentación en el código que la mayoría de las veces es innecesario.

lunes, 20 de diciembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 14 de diciembre de 2021
Protocolo HTTP Como sabemos, en las peticiones HTTP se envían al servidor un conjunto de “parámetros” o encabezados que añaden información extra para que la solicitud pueda ser procesada correctamente. Ahí encontramos información sobre el lado cliente, como la cadena de agente de usuario (encabezado user-agent), información sobre la propia petición, como el host al que se dirige la petición (encabezado host) o los idiomas que se aceptan para el contenido (accept-language), e incluso información contextual como las cookies del usuario (cookie) o información de autorización (authorization), entre muchos otros.

Hoy vamos a detenernos en una curiosidad histórica sobre el protocolo HTTP y uno de sus más célebres encabezados :)
lunes, 13 de diciembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 7 de diciembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 30 de noviembre de 2021
.NET

Cuando aparece una nueva versión de C# o .NET, los titulares de las noticias, tweets y posts suelen girar en torno a las novedades más destacadas, aquellas que suponen cambios importantes respecto a versiones anteriores. Pero es habitual que, aparte de éstas, se añadan otras características más pequeñas que muchas veces pasan desapercibidas.

Esto es lo que ocurre con al atributo [CallerArgumentExpression], una joyita de C#10 que puede ayudarnos a hacer más descriptivos los mensajes de error y trazas que guardamos cuando aparece un error en nuestras aplicaciones.

lunes, 29 de noviembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 23 de noviembre de 2021
.NET

Estamos muy acostumbrados a comenzar nuestros métodos realizando comprobaciones para evitar que pasen a nuestro código valores nulos que pudieran romper la aplicación.

Desde el principio de los tiempos, estas guardas han presentado el siguiente aspecto:

public class MyService
{
    public void MyMethod(object first, object second)
    {
        if(first == null) 
        {
            throw new ArgumentNullException("first");
        }
        if(second == null) 
        {
            throw new ArgumentNullException("second");
        }        
        // ...
    }
}    

¿Todo bien, verdad? El código es aparentemente correcto y fácil de comprender, pero... ¡demasiado extenso! Hemos consumido casi diez líneas de código sólo realizando comprobaciones de "fontanería", y ni siquiera hemos empezado a plantear la funcionalidad real del método.

Afortunadamente, con el tiempo C# ha ido evolucionando y mejorando sucesivamente este escenario tan frecuente.

lunes, 22 de noviembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 16 de noviembre de 2021
Blazor

Hasta Blazor 6, daba la impresión de que la query string era un ciudadano de segunda clase en el sistema de routing, pues no se ofrecían mecanismos sencillos para la obtención de parámetros suministrados a través de esta vía, ni tampoco para la generación de URI que los utilizaran. De hecho, estas tareas teníamos que solucionarlas manualmente, aunque fuera con ayuda de paquetes externos como Microsoft.AspNetCore.WebUtilities.

Ya con la llegada de esta versión, Blazor incorpora de serie herramientas que nos harán esto más llevadero, como su integración con el binding o, lo que veremos en este post, la posibilidad de generar direcciones que incluyan este tipo de parámetros.

lunes, 15 de noviembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada, obviamente muy condicionados por la oleada de lanzamientos de nuevas versiones de casi todo. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

lunes, 8 de noviembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 2 de noviembre de 2021
Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 26 de octubre de 2021
.NET Core Hoy va un post rapidito sobre un curioso detalle sintáctico de C# que me llamó la atención hace algún tiempo, mientras leía el artículo How to Stress the C# Compiler, donde Henning Dieterichs comenta varias formas de estresar (¡literalmente!) al compilador de C# utilizando construcciones admitidas por el lenguaje.

La cuestión es: ¿por qué no compila el siguiente código?
class Program {
    public static void Main() {
        int f = 0; int x = 0; int y = 0;
        System.Console.WriteLine(
            "{0} {1}",
            f < x,   // is f smaller than x?
            y > (-1) // is y greater than -1?
        );
    }
}
lunes, 25 de octubre de 2021

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET