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 ;)

17 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!
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...

Los "sabores" de Blazor: client-side, server-side... y otros

Inicialmente, la idea de Blazor era conseguir ejecutar el código C# en el browser llevando a éste una versión deducida del runtime de .NET. Este enfoque suele conocerse como Blazor WebAssembly o client-side, pues se basa en llevar físicamente al browser la ejecución de la parte cliente de la aplicación web.

WebAssembly La clave del funcionamiento de Blazor client-side es un runtime de .NET que corre sobre WebAssembly (WASM), una especificación abierta que define un "lenguaje ensamblador" común a todas las máquinas virtuales presentes en los navegadores modernos (y pollyfillable para los anteriores). Sobre ese runtime, ya en el lado cliente, es donde corren nuestras aplicaciones Blazor cuando elegimos este modelo de hospedaje.

Así, la primera vez que un usuario accede a una aplicación Blazor WebAssembly, su navegador descarga tanto el runtime de .NET como los ensamblados propios de la aplicación (compilados desde C# en tiempo de desarrollo) y sus dependencias. Ya tras esta descarga inicial, que gracias al caché de los navegadores se realizaría sólo una vez, los ensamblados de la aplicación serían ejecutados por el runtime directamente desde el navegador.

Un detalle importante a tener en cuenta es que el hecho de que el código cliente de nuestras aplicaciones lo desarrollemos usando .NET no significa que estemos llevando al cliente todo el potencial de esta plataforma. Dado que este código se ejecuta en cliente, al igual que cuando programamos con Javascript, estamos limitados por el sandbox proporcionado por el navegador para la ejecución segura de aplicaciones. Es decir, no podremos acceder a dispositivos o recursos locales más allá de los permitidos por las APIs estándar de los navegadores.

Por otra parte, como la ejecución se realiza puramente en cliente, no sería estrictamente necesario disponer de un servidor ASP.NET, IIS ni nada parecido. Tanto el runtime como los ensamblados resultantes de la compilación podrían ser distribuidos en un CDN, y es lo único que se necesitaría para poner en marcha la aplicación (bueno, a no ser que ésta necesite de un backend, claro.)

¿Y qué ventajas tiene esto? Pues bueno, ya el simple hecho de sustituir Javascript por C# para implementar el lado cliente puede aportarnos ventajas interesantes. Aparte de que C# es un lenguaje muy superior, también será posible utilizar o reutilizar bibliotecas .NET existentes, compartir código entre cliente y servidor, o utilizar entornos tan potentes como Visual Studio durante la fase de desarrollo.

Pero como siempre ocurre, no es la panacea; también provocará que la carga inicial de la aplicación sea más lenta (aunque, como decíamos, la caché podrá ayudarnos con esto), o requerirá que los clientes sean compatibles con WASM (aunque esto ya no es un problema en la mayoría de los casos).
Y bueno, de alguna forma nos alejaremos del ecosistema Javascript, que ya sabemos que es enorme, aunque también es cierto que desde Blazor es posible interoperar con bibliotecas JS existentes.
En la actualidad, Blazor WebAssembly sólo está disponible en preview, y está previsto lanzar la primera versión oficial en mayo de 2020 (aunque ésta aún no será LTS).
Como comentaba algo más arriba, el enfoque client-side de Blazor fue el origen del proyecto y sigue siendo el objetivo principal del mismo. Sin embargo, durante la fase de desarrollo aparecieron otros escenarios de uso de Blazor que podrían resultar interesantes y entraron a formar parte del Roadmap del producto, modificando los planes iniciales:

Blazor Roadmap

En la ilustración anterior podemos observar que el Roadmap posicionó Blazor Server como el primer hito del conjunto de tecnologías Blazor. De hecho, es el único framework del que tenemos a día de hoy una versión estable, production ready y con soporte a largo plazo.

Blazor Server parte del mismo objetivo que Blazor WebAssembly respecto a utilizar C# para la implementación de la lógica de presentación, aunque el enfoque que sigue es bastante diferente. En este caso no se trata de llevar todo al cliente sino al contrario: hacer que todo se ejecute en el servidor, comunicándose con el browser mediante una conexión persistente de SignalR:

Blazor WebAssembly vs Blazor Server

Para conseguirlo, el servidor mantiene en memoria una representación del estado de la página, que es modificada por mensajes SignalR que son enviados cuando se producen cambios o interacciones en la interfaz de usuario.

Por ejemplo, si un usuario pulsa un botón en la página, el evento "click" no es procesado en cliente sino enviado a través de la conexión SignalR al servidor, que ejecutará el handler oportuno (escrito en C#). Los cambios realizados en el UI desde dicho handler son enviados de vuelta al cliente, que actualizará el DOM de forma automática.
Pues sí, en cierto modo es muy similar a lo que utilizábamos en Web Forms años atrás, pero eliminando la pesadez del postback, la carga de página completa y el mantenimiento del estado mediante el célebre viewstate. De hecho, Blazor Server es la tecnología propuesta por Microsoft para sustituir a Web Forms, al promover un tipo de desarrollo conceptualmente muy parecido.
Como siempre ocurre, la idea tiene sus ventajas e inconvenientes. Como parte positiva respecto al modelo client-side, en este caso la carga inicial sería más rápida porque no hay nada que descargar desde el cliente. También, dado que el código se ejecutaría en el servidor, podríamos utilizar todo tipo de bibliotecas y componentes para .NET, así como las herramientas habituales de desarrollo y depuración. Y para casos de necesidad, este enfoque conseguiría casi el soporte universal por parte de los browsers, pues no requiere ninguna característica especial en el lado cliente.

Pero ah, amigos, todo esto no es gratis. El hecho de que cada interacción o evento en el UI deba ser enviado y procesado en el servidor añade una latencia que no todas las aplicaciones podrán soportar sin destrozar su usabilidad. Además, las conexiones concurrentes y el mantenimiento del estado en memoria podrían limitar las opciones de escalabilidad de los sistemas.

La buena noticia es que el modelo de componentes, y por tanto la forma de desarrollar, es la misma. De esta forma, podríamos iniciar un proyecto utilizando Blazor Server y migrar a Blazor WebAssembly más adelante con relativamente poco esfuerzo. Bueno, o al menos en teoría ;)

Pero aparte de Blazor Server y Blazor WebAssemby, y como veíamos en el Roadmap algo más arriba, el resto de tecnologías Blazor van acercándose consecutivamente a la ejecución nativa de aplicaciones, tanto desde dispositivos móviles como de escritorio:
  • Blazor PWA, para la construcción de Progressive Web Applications (PWA), webs que proporcionan una experiencia más cercana a las aplicaciones nativas al ser capaces de trabajar offline, recibir notificaciones push, o ser instaladas en los equipos de los usuarios. Sin embargo, la ejecución se realizará siempre sobre el sandbox proporcionado por el browser, por lo que tendremos las mismas limitaciones que si utilizáramos JS.
     
  • Blazor Hybrid, aplicaciones que correrán sobre Electron y renderizarán su UI utilizando tecnologías web sobre WebViews o motores de renderizado de webs. Dado que serán aplicaciones .NET puras, en este caso sí se podrá acceder a todos los recursos del equipo donde se instalen.
     
  • Blazor Native, que permitirá en el futuro utilizar el mismo modelo de programación para crear aplicaciones nativas puras, capaces de renderizarse utilizando componentes nativos de la plataforma de ejecución, fuera del mundo web. En la práctica, quiere decir que podríamos utilizar esta tecnología en lugar de Xamarin o React Native para implementar nuestras aplicaciones nativas.
Aunque muy sujeto a cambios, pero está previsto lanzar previews de PWA e Hybrid a finales de 2020, acompañando a .NET 5. La última referencia que he encontrado de Blazor Native es que está en fase experimental y, por tanto, no existen aún previsiones de disponibilidad.

Solución usando Mobile Blazor Bindings Aparte, hace apenas un par de días han anunciado otro giro de tuerca: Mobile Blazor Binding. Este proyecto, aún en fase experimental, permite utilizar el modelo de programación de Blazor y la sintaxis Razor para la construcción de aplicaciones nativas Android e iOS, en la práctica algo así como un híbrido entre Blazor y Xamarin. El objetivo es acercar al mundo de las apps nativas a esa gran masa de desarrolladores web acostumbrados a Razor, y la verdad es que tiene bastante buena pinta.

Esto promete, ¿eh? 😉

¿Cómo se desarrolla con Blazor?

Por si no os lo habéis preguntado, el nombre Blazor procede de la unión de "Browser" y "Razor" (la "L" no sé de dónde sale, supongo que dará más musicalidad al resultado :-P), así que ya podéis intuir por dónde van los tiros: Razor que se ejecuta en el navegador.

De hecho, los componentes y páginas Blazor se implementan utilizando sintaxis Razor, que muchos ya conocéis de otras películas como ASP.NET Core MVC o Razor Pages, aunque con algunos cambios. Por ejemplo, en Blazor las páginas o componentes se implementan en archivos .razor, a diferencia de los clásicos .cshtml de MVC o Razor Pages.

Pero como las cosas se suelen entender mejor con código, mejor que echéis primero un vistazo al siguiente archivo Sum.razor:
@page "/sum"

<h1>Calculator</h1>
<div>
    <input type="number" @bind-value="@A" />
    +
    <input type="number" @bind-value="@B" />
    <button @onclick="Calculate">Calculate</button>
</div>
@if (Result != null)
{
    <div>
        The sum of @A and @B is @Result
    </div>
}

@code {
    public int? A { get; set; }
    public int? B { get; set; }
    public int? Result { get; set; }

    void Calculate()
    {
        Result = A + B;
    }
}
Calculadora Blazor Echando un vistazo puede entenderse que se trata de una simple calculadora para realizar sumas que incluye un par de tags <input> para solicitar los sumandos y un botón para realizar el cálculo. Al pulsarlo, se muestra el resultado de la suma en un <div> que inicialmente no está visible.

Este bloque de código es suficiente para entender la magia de Blazor:
  • En el bloque @code, implementado por completo en C#, definimos todas las propiedades y métodos que necesitemos para implementar la lógica de nuestra página. En este caso, tenemos un par de propiedades para los sumandos, otra para el resultado, y un método que realiza el cálculo.
    @code {
        public int? A { get; set; }
        public int? B { get; set; }
        public int? Result { get; set; }
    
        void Calculate()
        {
            Result = A + B;
        }
    }
    
  • Utilizamos bindings sobre los controles HTML, muy al estilo de otros frameworks basados en MVVM, como Angular o React. En el ejemplo podemos ver que bindeamos el valor de los <input> a las propiedades definidas en el bloque @code, de la misma forma que establecemos el manejador del evento click al método Calculate().
    <input type="number" @bind-value="@A" />
    +
    <input type="number" @bind-value="@B" />
    <button @onclick="Calculate">Calculate</button>
    
  • Dado que usamos sintaxis Razor, es posible utilizar los habituales bloques de control de flujo como @if, @foreach, etc. En el caso anterior, usamos un condicional para añadir a la página el <div> con el resultado, pero sólo cuando hemos calculado la suma.
    @if (Result != null)
    {
        <div>
            The sum of @A and @B is @Result
        </div>
    }
    
Fijaos que hemos eliminado de un plumazo a Javascript, y la web funcionará sin cambiar de página, muy al estilo SPA:
  • Si hemos optado por utilizar el host Blazor Server, todos los eventos e interacciones sobre el UI (cambios de valores en controles bindeados, clicks, etc.) serán enviados al servidor a través de la conexión SignalR establecida automáticamente. El servidor ejecutará el código y enviará de vuelta al cliente, usando la misma conexión, las modificaciones a realizar en el DOM para actualizar la interfaz de usuario.

  • En cambio, si hemos optado por utilizar Blazor WebAssembly, la página será compilada y el ensamblado resultante será enviado al cliente, quien lo ejecutará sobre el runtime basado en WebAssembly. Por tanto, la ejecución de la página se realizará totalmente en cliente, como si la hubiéramos implementado totalmente Javascript, sin necesidad de interactuar con el servidor en ningún momento.
Y lo interesante es que en ambos casos nuestro código será el mismo. Es decir, la página Sum.razor podrá ser (en teoría) la misma para cualquiera de los modelos de ejecución de Blazor, por lo que podríamos crear nuestras aplicaciones e ir evolucionando posteriormente de un modelo a otro. Por ejemplo, a día de hoy sólo podríamos poner aplicaciones Blazor en producción usando Blazor Server, pero en unos meses podríamos pasar al modelo WebAssembly cuando esté disponible, realizando pocos cambios.

Pero no sólo eso, la idea también aplica para el resto de "sabores" de Blazor, como PWA, Hybrid o Native: lo único que cambiará es el "empaquetado" y, en algunos casos, el proceso interno de renderizado, pero nuestro código seguirá siendo principalmente el mismo... o al menos, estas son las intenciones iniciales; conforme avancen estos proyectos iremos viendo hasta qué punto es así.

En definitiva, Blazor es un framework del que seguro vamos a oír hablar bastante durante los próximos meses, y no sin razón. Aunque aún está empezando a rodar y quedan bastantes cosas por pulir, es conveniente no perderlo de vista porque realmente las expectativas están muy altas :)

Publicado en Variable not found.

20 Comentarios:

José Manuel Alarcón dijo...

¡Sensacional resumen José María!

José María Aguilar dijo...

Muchas gracias, José Manuel :)

Unknown dijo...

Una excelente explicación, saludos y gracias

José María Aguilar dijo...

Muchas gracias!

Unknown dijo...

La verdad es un excelente articulo, yo decidi aprender C# hace apenas unas semanas, sin saber que alternativas existen a AngularJS que es el framework que llevo mil años usando, y de pronto como si el destino hubiera plantado una semilla en mi, me entero que existe Blazor y sus dos sabores (hasta el momento), y me entusiasme y me puse a jugar con el framework y con el lenguaje , leyendo documentacion de ambas cosas y haciendo experimentos de rendimiento.

Puedo decir que la version cliente si bien "promete" más, es lentísima para iniciarse, es muy fastidioso el "Loading", que supongo q eventualmente se podrá personalizar.

La versión de servidor me gusta muchisimo, siento que el codigo esta mas protegido y tengo la posibilidad de tener una logica de backend y bases de datos ahi mismo. Creo que Webassembly no es una tan idea, el peso del paquete final es mucho mayor que con un framework como AngularJS, aunque supongo q en la version final arreglarán eso. En fin, ahora quedé expectante de ver las demás versiones jaja, especialmente la de móvil.

José María Aguilar dijo...

Hola, desconocido! :D

Muchas gracias por tu comentario.

Efectivamente, la versión cliente promete mucho. Están trabajando en la reducción del peso de la descarga inicial y seguro que será mucho menos, aunque siempre tendremos que descargar algo (en todos los frameworks ocurre); la cuestión es pensar que en producción la caché se hará cargo de ello la mayoría de las veces.

Respecto al "loading", sí, es personalizable, escribiré un post sobre ello un día de estos.

Un saludo!

Unknown dijo...

No sé por qué salgo con este nombre pero en fin. El problema que le veo a webassembly es que de todas maneras vas a necesitar un backend para conectarte a una DB o subir cosas a S3 sin poner las credenciales en el código del cliente, ya que siempre te lo podrán decompilar, y por eso me gusta mucho la solución server side. Qué opinas tú de esto? Si usaras WASM que usarlas de backend?

José María Aguilar dijo...

Hola!

El escenario es idéntico al que encontrarías si utilizase otro framework SPA como Angular o React: siempre deberás tener un backend que proporcione Las funcionalidades que no puedes o debes llevar a cliente por razones de seguridad o posibilidades técnicas.

Respecto a tu segunda cuestión, por supuesto usaría ASP.NET Core ;)

Saludos!

Unknown dijo...

Gracias por la respuesta :)

Quiero ver si entendí bien: ¿aún con el blazor server-side necesitaría un backend? ¿acaso no es un backend en sí mismo que se puede conectar a una Db?

Respecto a lo de usar ASP.NET Core no lo entiendo tampoco, ¿eso no es un framework para front? ¿cómo haces un backend con eso?

Por otro lado ayer descubrí que el template de Blazor trae una opción de integrar Login con la nube usando AD B2C, que por cierto es gratis hasta 50.000 usuarios!

José María Aguilar dijo...

Hola!

Disculpa, igual no te entendí o no me expliqué bien.

Con lo del backend me refería a Blazor WebAssembly. Con Blazor Server estás ejecutando siempre código en el servidor y puedes conectar con bases de datos o con lo que necesites sin problema.

Centrados ya en Blazor WebAssembly, hablaba de que desarrollaría el backend con ASP.NET Core, y más concretamente con las herramientas para el desarrollo de APIs web que incorpora (ASP.NET Core MVC/Web API). Con este framework puedes crear "endpoints" en el servidor listos para responder a peticiones procedentes del frontal (la aplicación SPA Angular, React o Blazor Wasm).

Saludos!



Fernando Gutiérrez dijo...

Excelente artículo!

José María Aguilar dijo...

Muchas gracias, Fernando!

Albert dijo...

Excelente artículo como todos tus artículos! Una pregunta, para cuando un curso de blazor? Estoy pensando en realizar tu curso asp.net core en campus Mvp y me gustaría completarlo con blazor, vas a sacar algo?
Gracias!

José María Aguilar dijo...

Hola Albert! Muchas gracias por tus comentarios :)

Respecto a tu pregunta, de momento no estoy trabajando en ello por dos motivos. Primero, porque es demasiado pronto: la experiencia nos ha enseñado que las versiones iniciales de los frameworks son incompletas y muy cambiantes, y Blazor aún tiene una de sus grandes apuestas (Blazor Webassembly) en preview. Segundo, porque para crear un curso de un framework nuevo hay que conocerlo en profundidad, y aún estoy en ello ;)

Pero en cualquier caso, te animo a que aprendas ASP.NET Core, pues te será de mucha utilidad para cuando comiences con Blazor, ya sea siguiendo un futuro curso de CampusMVP o bien si lo aprendes a tu aire. En el caso de Blazor Server, éste se apoya totalmente en la infraestructura proporcionada por ASP.NET Core, por lo que mucho de lo que aprendas te servirá, y para Blazor WebAssembly necesitarás crear APIs, y con MVC/Web API encontrarás una herramienta fantástica para ello.

Saludos!

Albert dijo...

Gracias a ti por contestar. Pues parece que Blazor va en serio, siempre he fallado mucho en el frontend, siempre me ha dado mucha pereza, quizás blazor ayude. Pero primero me voy a poner con asp.net core a estudiarlo en profundidad con tu curso en campus mvp, ya he hecho otros tuyos allí (ASP.net mvc 4 y 5) y me parecen la mejor forma de aprender. Nos vemos pronto por campusmvp, seguro te molestaré con innumerables preguntas ;) (pero con mi verdadero nombre, no Albert :S ) ah, si necesitas revisor para un futuro curso de Blazor en campusmvp o donde sea puedes contar conmigo ;), ya hablaremos desde campusmvp. Gracias de nuevo!!

Anónimo dijo...

Muy bien explicado estimado, se agradece el aporte. Saludos. Rafael.

José María Aguilar dijo...

Muchas gracias, Rafael, espero que te haya resultado útil :)

Enrique Granados dijo...

Muchas gracias , me sirvió bastante el articulo . Me da gusto pensar que poco a poco me he puesto en sinfonía con lo ultimo en .Net ; por otro lado , ha sido difícil para mi interpretar de momento la escueta información en sitios oficiales ,por lo cual este articulo es de mucha ayuda, debido a lo reciente del tema.
Saludos!

José María Aguilar dijo...

Muchas gracias a ti, Enrique. Me alegra saber que te resultó útil :)

Saludos!

Unknown dijo...

Excelente, creo que no podria quedar mas claro!!
Eso si .. como esto avanza rapidamente.. falta una actualización..