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, 4 de mayo de 2020
Enlaces interesantes El (relativamente desconocido) código de estado HTTP 402 (Payment required) se reservó para usos futuros hace más de veinte años, pensando que en algún momento se utilizaría para indicar al lado cliente que la operación solicitada requería "pasar por caja" antes de ser ejecutada.

Sin embargo, la idea nunca se desarrolló y, a falta de una especificación formal, no se generalizó su uso. Personalmente, jamás he implementado una API o servicio que retorne HTTP 402, pero hay algunos proveedores de servicios que sí lo hacen, aunque de forma arbitraria y no normalizada.

Esta era la píldora cultural del día, vamos con el tema que nos ocupa :)

Seguimos de encierro una semana más, aunque ya con la posibilidad de disfrutar de pequeños paseos (limitados en tiempo y distancia) o de hacer deporte en el exterior. Esto hace que el futuro se vea con algo más de optimismo, aunque espero que esta tímida apertura no provoque una vuelta atrás en los avances conseguidos hasta el momento.

Y mientras la cosa se aclara, podéis ir echando un vistazo a los enlaces recopilados durante la semana pasada que, como de costumbre, espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 28 de abril de 2020
Blazor Hoy va un truquillo rápido sobre Blazor que puede resultar útil en muchos escenarios. Como probablemente sepáis, al igual que ocurre con otras tecnologías, Blazor codifica la salida HTML por motivos de seguridad, de forma que cualquier contenido con código de marcado será mostrado por defecto tal cual, sin interpretar las etiquetas.

Por ejemplo, considerad el siguiente código en un componente Blazor:
<p>This text is encoded: @myHtml</p>

@code {
    string myHtml = "Hello, <b>this is bold</b>";
}
El resultado que enviaremos al navegador es el siguiente:
<p>This text is encoded: Hello, &lt;b&gt;this is bold&lt;/b&gt;</p>
Y, por tanto, nuestros usuarios podrán leer literalmente este párrafo:
This text is encoded: Hello, <b>this is bold</b>
Normalmente no es eso lo que queremos mostrarles, ¿verdad?
lunes, 27 de abril de 2020
Enlaces interesantes Aunque seguimos en el túnel, parece que tímidamente está apareciendo un poco de luz en la lejanía. Y mientras la cosa se ilumina del todo, quizás os entretengan un rato los enlaces recopilados durante la semana pasada, que, como de costumbre, espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 21 de abril de 2020
Blazor Es lógico pensar que muchas de las aplicaciones que construyamos con Blazor, sobre todo en el mundo empresarial, necesitarán acceder a bases de datos para obtener o almacenar información.

En caso de utilizar Blazor WebAssembly, ese acceso encajará conceptualmente con lo que venimos haciendo desde hace años al construir aplicaciones SPA: desde el lado cliente simplemente llamaremos a una API o endpoint que actuará como pasarela, por lo que todo el código de acceso a datos se encontrará en el servidor. Aunque existen algunas iniciativas para posibilitar que EF Core funcione directamente en el navegador con algunos proveedores, ciertamente no será el escenario habitual.

Sin embargo, si utilizamos Blazor Server, tendremos la sensación inicial de que es todo más sencillo. El código de eventos bindeados a la interfaz se ejecuta en servidor, por lo que a priori sólo tendríamos que replicar lo que solemos hacer con servicios o controladores: solicitar una instancia del contexto de datos al inyector de dependencias, y utilizarla para lograr nuestros propósitos.

Pero no, la cosa es algo más complicada que eso. De hecho, los que ya estéis creando aplicaciones Blazor Server con EF Core seguro que os habéis topado en algún momento con un error como el siguiente:
InvalidOperationException: A second operation started on this context before a previous operation 
completed. This is usually caused by different threads using the same instance of DbContext. For 
more information on how to avoid threading issues with DbContext, see 
https://go.microsoft.com/fwlink/?linkid=2097913.
Esta excepción se debe a que existen dos hilos de ejecución utilizando la misma instancia del contexto de datos al mismo tiempo, algo que Entity Framework no permite. Esto ocurrirá, por ejemplo, si tenéis en la misma página varios componentes que de forma concurrente intentan acceder a la base de datos al inicializarse.

¿Por qué ocurre esto?
lunes, 20 de abril de 2020
Enlaces interesantes Pues recién cumplidos los diez años desde que comencé a publicar enlaces de interés todas las semanas, vamos ahora a por la entrega número 400. Como siempre, espero que os resulten interesantes y os ayuden a llevar mejor estos días :)

Por si te lo perdiste...

.NET Core / .NET

martes, 14 de abril de 2020
Enlaces interesantes Es increíble lo rápido que pasa el tiempo: aunque parezca que fue ayer, hace ya diez años que comencé a publicar enlaces interesantes en el blog, iniciando la serie con el post Enlaces interesantes 1... y en estos momentos estoy preparando la entrega semanal número 400 :)

Y para celebrarlo, he pensado que estaría bien hacer un recopilatorio de preguntas y curiosidades que los fieles seguidores de esta serie me habéis ido haciendo llegar, tanto en persona como a través de redes sociales o mails, a lo largo de estos años.
lunes, 13 de abril de 2020
Enlaces interesantes Una semana más de confinamiento, pero una semana menos para que esta pesadilla termine. Y mientras tanto, sigamos compartiendo enlaces que, como de costumbre, espero que os resulten interesantes :)

Por si te lo perdiste...

.NET Core / .NET

lunes, 6 de abril de 2020
Enlaces interesantes Dado que la recopilación de enlaces ha sido considerada una actividad esencial, no se ha visto afectada por el parón decretado recientemente, así que ahí va la cosecha de la semana pasada :)

Como siempre, espero que os resulten interesantes y os ayuden a llevar mejor el confinamiento. ¡Que paséis una buena Semana Santa!

Por si te lo perdiste...

.NET Core / .NET

martes, 31 de marzo de 2020
ASP.NET Core Como sabemos, hasta ASP.NET Core 2.2, registrábamos los servicios de MVC y Razor Pages en el método ConfigureServices() de la clase Startup con una línea como la siguiente:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    ...
}
Esto era todo lo que necesitábamos para poder utilizar cualquiera de estas tecnologías en nuestra aplicación. Sin embargo, a partir de ASP.NET Core 3.0, nuestro intellisense se vio inundado de opciones adicionales como AddControllers(), AddRazorPages() AddControllersWithViews().

¿Para qué sirven, y por qué ha sido necesario introducir estos nuevos extensores?
lunes, 30 de marzo de 2020
Enlaces interesantes Pues otra semana de encierro, y otro buen número de enlaces recopilados que, como de costumbre, espero que os resulten interesantes.

¡Cuidaos mucho!

Por si te lo perdiste...

.NET Core / .NET

martes, 24 de marzo de 2020
Blazor Al comenzar con Blazor, seguro que veis en la mayoría de ejemplos que la implementación de la lógica (código C#) y de la pura interfaz de usuario (HTML) se encuentran en un bloque @code en el mismo archivo .razor, como en el siguiente bloque de código:
@* File: ~/Pages/HelloWorld.razor *@
@page "/hello"
<h1>Hello</h1>
<div>
    <label for="name">Your name:</label>
    <input id="name" @bind-value="Name" @bind-value:event="oninput"/>
</div>
@if (HasName)
{
    <h2>Hello, @Name!</h2>
}

@code
{
    public string Name { get; set; }
    public bool HasName => !string.IsNullOrWhiteSpace(Name);
}
Sin embargo, esto no tiene que ser necesariamente así. En tiempo de compilación, un archivo .razor genera una clase parcial C# con su mismo nombre, lo cual nos brinda la posibilidad de mover todo el código C# a otra porción de dicha clase.
Podéis ver las clases generadas para cada archivo .razor en la carpeta del proyecto obj\debug\netcoreapp3.1\Razor\Pages.

lunes, 23 de marzo de 2020
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os entretengan, al menos un ratillo, durante el confinamiento :-)

Por si te lo perdiste...

.NET Core / .NET

martes, 17 de marzo de 2020
.NET Core Hace unos días han anunciado la disponibilidad de una herramienta que os puede interesar si, como un servidor, acumuláis un gran número de versiones del SDK y runtimes de .NET Core que no váis a necesitar, algo muy propio de ese Diógenes digital que todos llevamos dentro ;)

El estado actual de acumulación de SDKs podéis conocerlo muy fácilmente desde línea de comandos utilizando la orden dotnet --list-sdks:
C:\>dotnet --list-sdks
1.1.11 [C:\Program Files\dotnet\sdk]
2.1.202 [C:\Program Files\dotnet\sdk]
2.1.503 [C:\Program Files\dotnet\sdk]
2.1.504 [C:\Program Files\dotnet\sdk]
2.1.505 [C:\Program Files\dotnet\sdk]
2.1.507 [C:\Program Files\dotnet\sdk]
2.1.508 [C:\Program Files\dotnet\sdk]
2.1.509 [C:\Program Files\dotnet\sdk]
2.1.511 [C:\Program Files\dotnet\sdk]
2.1.602 [C:\Program Files\dotnet\sdk]
2.1.604 [C:\Program Files\dotnet\sdk]
2.1.700 [C:\Program Files\dotnet\sdk]
2.1.701 [C:\Program Files\dotnet\sdk]
2.1.800-preview-009696 [C:\Program Files\dotnet\sdk]
2.1.801 [C:\Program Files\dotnet\sdk]
2.1.802 [C:\Program Files\dotnet\sdk]
2.2.102 [C:\Program Files\dotnet\sdk]
2.2.105 [C:\Program Files\dotnet\sdk]
2.2.202 [C:\Program Files\dotnet\sdk]
2.2.203 [C:\Program Files\dotnet\sdk]
2.2.204 [C:\Program Files\dotnet\sdk]
3.0.100-preview8-013656 [C:\Program Files\dotnet\sdk]
3.0.100-preview9-014004 [C:\Program Files\dotnet\sdk]
3.0.100 [C:\Program Files\dotnet\sdk]
3.1.100 [C:\Program Files\dotnet\sdk]
3.1.101 [C:\Program Files\dotnet\sdk]
3.1.102 [C:\Program Files\dotnet\sdk]

C:\>_
En mi caso, tengo aún por ahí el SDK de .NET Core 1.x, un par de decenas de .NET Core 2.x, y algunas previews, pero los he visto mucho peores ;) Obviamente, salvo dos o tres versiones que quizás me interesen porque tengo aplicaciones que aún no he migrado, el resto ocupan en mi equipo un espacio considerable sin motivo, más de 5GB, pues cada SDK puede pesar entre 150 y 200 Mb.
lunes, 16 de marzo de 2020
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes, ¡y que los veáis desde casa, que la cosa se está poniendo muy muy fea! ¡Cuidaos mucho!

Por si te lo perdiste...

.NET Core / .NET

martes, 10 de marzo de 2020
.NET Core Alguna vez he escuchado, a modo de leyenda urbana, que no era bueno utilizar try/catch porque el mero hecho de usar este tipo de bloque de código afectaba al rendimiento.

La verdad es que de forma intuitiva se puede adivinar que esto no debería ser así. Si no se producen excepciones en un código que tengamos envuelto en un try/catch se debería ejecutar virtualmente a la misma velocidad que si no usáramos este tipo de bloque. Cosa distinta es si producen excepciones: ahí el rendimiento sí se verá seriamente penalizado, pero no es culpa del try/catch sino del propio sistema de gestión de excepciones de .NET.

Pero claro, lo dicho anteriormente es sólo cierto si somos capaces de demostrarlo, así que usaremos nuestro viejo conocido BenchmarkDotnet para desmontar este mito.
lunes, 9 de marzo de 2020
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, 2 de marzo de 2020
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 febrero de 2020
.NET Core Pues va un post cortito a modo de autorecordatorio, porque es algo que me ha pasado ya varias veces y siempre tengo que ponerme a investigar cómo solucionarlo.

Personalmente me gusta tener todos los entornos y herramientas de desarrollo en inglés, básicamente porque cuando encontramos problemas es más fácil encontrar soluciones si a la hora de buscar utilizamos los términos en este idioma... bueno, y de paso, evito ver algunas traducciones terribles ;)

Pues bien, en el caso del SDK de .NET Core, el idioma no es una característica que podamos elegir a la hora de instalarlo. Se instalarán todos los idiomas disponibles (podéis verlo por ejemplo en la carpeta %programfiles%\dotnet\sdk\3.1.101), y los mensajes se mostrarán en el idioma configurado por defecto en nuestra máquina. En mi equipo, por ejemplo, se muestra todo en idioma español:
C:\>dotnet xyz
No se pudo ejecutar porque no se encontró el comando o archivo especificados.
Algunas de las posibles causas son:
  * Escribió mal un comando dotnet integrado.
  * Intentó ejecutar un programa .NET Core, pero dotnet-xyz no existe.
  * Tiene planeado ejecutar una herramienta global, pero no se encontró un ejecutable 
    con prefijo dotnet con este nombre en la RUTA DE ACCESO.

C:\>_
lunes, 24 de febrero de 2020
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 febrero de 2020
ASP.NET Core MVC En muchas ocasiones, la llegada de una nueva versión de un framework viene acompañada de documentación, posts y otro tipo de contenidos que anuncian a bombo y platillo las principales novedades y cambios introducidos. Ante este ruido, es fácil pasar por alto otros pequeños cambios que introducen mejoras a los marcos de trabajo o simplemente permiten ir evolucionando código antiguo a funcionalidades más recientes.

Hoy vamos a hablar de una de eso pequeños descubrimientos: el rutado dinámico de controladores. Introducido en ASP.NET Core 3, se trata de una característica que no ha sido especialmente publicitada ni comentada, pero puede ser de utilidad en algunas ocasiones, pues permite interferir en la forma de interpretar las rutas de las peticiones entrantes con objeto de decidir en cada caso cómo deben ser procesadas.
lunes, 17 de febrero de 2020
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 febrero de 2020
.NET Core Como sabemos, para ejecutar cualquier tipo de aplicación .NET Core en un equipo necesitamos tener instalado el runtime o el SDK de la plataforma. Esto es algo que podemos hacer muy fácilmente, simplemente acudiendo a la página oficial de descargas, eligiendo nuestro sistema operativo y siguiendo las instrucciones de instalación.

El hecho de que en el equipo destino esté preinstalado el runtime es muy interesante, entre otras cosas porque permite asegurar de antemano que en él se encontrarán todas las dependencias (frameworks, bibliotecas, paquetes, metapaquetes) necesarios para una correcta ejecución. Por tanto, para distribuir nuestra aplicación sólo debemos generar lo relativo a nuestro código, el resto ya estará allí.
Esta forma de publicar aplicaciones se denomina framework-dependent, pues dependen de que determinados componentes del framework estén instalado en el destino.
Por ejemplo, el paquete de publicación de una aplicación de consola prácticamente vacía, que únicamente muestra el mensaje "Hello world!", ocuparía solo 175K:
D:\MyConsoleApp\output>dir

 El volumen de la unidad D es Datos
 El número de serie del volumen es: 8CBC-81E3

 Directorio de D:\MyConsoleApp\output

09/02/2020  18:47    <DIR>          .
09/02/2020  18:47    <DIR>          ..
09/02/2020  18:46               428 MyConsoleApp.deps.json
09/02/2020  18:46             4.608 MyConsoleApp.dll
09/02/2020  18:46           169.984 MyConsoleApp.exe
09/02/2020  18:46               668 MyConsoleApp.pdb
09/02/2020  18:46               154 MyConsoleApp.runtimeconfig.json
               5 archivos        175.842 bytes
               2 dirs  463.058.874.368 bytes libres

D:\MyConsoleApp\output>_
Otra ventaja de este tipo de distribución es que es cross platform pura, es decir, podemos copiar los archivos a cualquiera de los sistemas operativos soportados y, siempre que dispongan del runtime, nuestra aplicación podrá correr sobre ellos sin problema.

Y todo esto está muy bien, pero, ¿qué pasa si quiero crear una aplicación portable, de forma que pueda distribuirla y ejecutarla sin necesidad de que el equipo destino tenga nada preinstalado?

Pues eso es lo que veremos en este post ;)
lunes, 10 de febrero de 2020
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, 4 de febrero de 2020
Open API Días atrás veíamos cómo utilizar Swashbuckle para generar automáticamente la descripción OpenAPI de APIs creadas con ASP.NET Core MVC y ponerlas a disposición de los consumidores en una ruta específica:
  Descripción OpenAPI de una API

En este post vamos a ver un par de formas de sacar provecho de esta descripción:
  • En primer lugar, usaremos Swagger UI para generar un sitio web interactivo de documentación y pruebas de nuestra API.
  • Después, veremos cómo generar desde Visual Studio código cliente para acceder a la API.
lunes, 3 de febrero de 2020
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, 28 de enero de 2020
Open API La OpenAPI Specification (OAS) es un estándar abierto para la descripción de APIS REST promovido por la Iniciativa OpenAPI, un consorcio de compañías de primer nivel como Microsoft, Google, IBM, Paypal y otros.

El objetivo de OpenAPI es conseguir una fórmula normalizada para describir las capacidades de un servicio REST, independientemente de los lenguajes o tecnologías con las que sea implementado. Esta descripción, normalmente especificada en formato JSON o YAML, permite a clientes (sean humanos o máquinas) descubrir servicios, comprender sus capacidades y conocer sus detalles de funcionamiento sin necesidad de tener acceso a su código fuente o documentación textual.

Esta especificación formal abre interesantes posibilidades, pues a partir de la definición estandarizada de servicios es posible, entre otros,
  • disponer de herramientas de diseño y modelado de servicios,
  • generar automáticamente páginas de documentación,
  • generar automáticamente código cliente y servidor para dichos servicios para distintos, frameworks y lenguajes de programación,
  • generar automáticamente código de testing y validaciones,
  • o generar automáticamente mocks de servicios.

lunes, 27 de enero de 2020
Enlaces interesantes Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET

martes, 21 de enero de 2020
Blazor Recuerdo que la primera vez que, en una de mis visitas a Redmond, vi a Steve Sanderson haciendo una demo de Blazor "en vivo" me pareció casi magia: una aplicación web SPA cuya lógica de presentación y UI se implementaba exclusivamente en C#, eliminando por completo de la ecuación a Javascript. ¡Uau!

En aquellos tiempos era aún poco más que un prototipo y no se podía saber si aquella línea de investigación llevaría a alguna parte, pero era tan prometedor que, algún tiempo después, a primeros de 2018, Blazor pasó a ser un proyecto experimental del equipo ASP.NET de Microsoft.

A partir de ese momento se fueron despejando las incógnitas que quedaban en cuanto a la viabilidad real de convertir aquello en un producto y se continuaron implementando funcionalidades, hasta que, en abril de 2019, Daniel Roth anunció que daban por concluida la fase experimental y Blazor entraba oficialmente a formar parte del stack de tecnologías para la web.

A día de hoy, Blazor es un framework completo para el desarrollo de aplicaciones web SPA, como lo pueden ser Angular, React o Vue. Dispone de sistema de bindings, routing, componentes, ciclo de vida, validaciones, plantillas, gestión de errores, inyección de dependencias, etc. Todo lo que podemos necesitar para crear aplicaciones web profesionales de calidad.

La primera versión de Blazor se lanzó acompañando a .NET Core 3.0 en Septiembre de 2019, aunque sólo en uno de sus modelos de hospedado: el denominado server-side o Blazor Server.

Pero no era ese el único plan...