Construye un FrontEnd Web con Blazor

Construye un FrontEnd Web con Blazor

La historia cuenta que la construcción de interfaces gráficas para la Web ha estado completamente dominada por Javascript, hasta ahora, pues con el surgimiento de nuevas formas de construir aplicaciones para la web, entre ellos WebAssembly, se han incorporado al portafolio de opciones nuevas herramientas.

Acá es donde aparece Blazor: La plataforma propuesta por Microsoft para la construcción de aplicaciones web usando .NET que elimina - casi - por completo la necesidad de usar Javascript.

No caeré en el clic-bait de decir que vas a construir web sin Javascript, pero si podré asegurar que en la mayoría de los entornos no encontrarás la necesidad de usarlo, salvo casos muy especiales.

Blazor es un marco web de front-end de .NET que admite la representación del lado servidor y la interactividad del cliente en un único modelo de programación:

  • Permite crear las interfaces de usuario con C#. mediante HTML y CSS para la compatibilidad con todos los exploradores, incluidos los móviles.

  • La lógica de aplicación del lado cliente y servidor escrita con .NET.

  • Puede usarse para aplicaciones híbridas de escritorio y móviles con .NET y Blazor.

El uso de .NET para el desarrollo web en el lado cliente ofrece las siguientes ventajas:

  • Escritura de código en C#, lo que puede mejorar la productividad en el desarrollo y el mantenimiento de aplicaciones.

  • Aprovechamiento del ecosistema .NET existente de bibliotecas .NET.

  • Beneficios de rendimiento, confiabilidad y seguridad de .NET.

  • Compile sobre un conjunto común de lenguajes, marcos y herramientas que son estables, completos y fáciles de usar.

En Blazor podrá escribir aplicaciones que se ejecuten:

  1. Del Lado del Cliente usando WebAssembly, una tecnología que permite que el código sea cargado en el navegador (como pasa con JavaScript) y que se ejecute directamente del lado del cliente.

  2. Del Lado del Servidor. Donde ASPNET Core compila y ejecuta el código entregando el código ya listo para ser renderizado en HTML y CSS

Con .NET tenemos una opción mucho mejor y es juntar ambos mundos y poder decidir cuándo usar una opción u otra. Por ahora usaremos lo básico de Blazor.

Creación del Proyecto

💡
Si no has descargado el código hasta el momento puedes hacer en Release V1 · parejajd/WebApiEstaciones (github.com)

El proyecto lo crearemos usando las herramientas de Visual Studio Code, seleccionando en la barra de tareas > .NET: New Project ...

Y seleccionando Blazor WebAssembly StandAlone App

Estos nos creará un proyecto con la siguiente estructura

Veamos de que se trata cada carpeta y archivo

  • Layout contiene dos elementos, la plantilla MainLayout que determina la estructura general, si abres el archivo verás que tiene contenido HTML

  • Pages son las páginas de nuestro proyecto, donde ubicaremos el contenido que será mostrado al visitante del sitio

  • Properties son archivos de configuración

  • wwwroot carpeta donde puede ubicarse el código estático Hojas de Estilo, Imágenes, Archivos Javascript, etc

  • _Imports.razor archivo donde se configuran las importaciones generales del proyecto

  • App.razor es el componente que tiene el punto de entrada de nuestra aplicación web

  • Program.cs contiene todo el código de inicialización de la aplicación, la inyección de dependencias, configuración de accesos a servicios web, etc

Si te curiosidad, puedes ingresar a la carpeta BlazorWeb y lanzar este comando

dotnet watch

Este comando compila y ejecuta el proyecto y queda atento a los cambios para realizar de nuevo el proceso, veras en la salida de esa consola un texto como este Now listening on: localhost:xxxx

Da clic en esa ruta o ingresala en el navegador y tendrás ya el sitio ejecutandose

Reutilización de código

En nuestra arquitectura hemos creado un proyecto llamado Modelos, por ahora sin entrar en mayor rigor de arquitectura, este proyecto contendrá el contenido que compartiremos y es necesario agregarlo al proyecto de BlazorWeb

dotnet sln add .\BlazorWeb\

Para que el comando funcione correctamente debemos estar ubicados en la raíz de la carpeta de nuestra solución

Ahora vamos a agregar la referencia de Modelos a nuestro proyecto BlazorWeb

dotnet add .\BlazorWeb\ reference .\Modelos\

Conexión del Front al API

Este paso nos permitirá consultar y crear posteriormente estaciones de servicio y para hacerlo nuestro Blazor debe conocer la ruta del API. Preparemos el entorno para eso permitiendo que se ejecuten ambos proyectos (El WebApi y el BlazorWeb), para esto, en la carpeta .vscode, crea un archivo con el nombre tasks.json con el siguiente código

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Compilar WebApi",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/WebApi/WebApi.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "Compilar Blazor",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/BlazorWeb/BlazorWeb.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary"
            ],
            "problemMatcher": "$msCompile"
        }
    ]
}

Ahora crea un archivo con el nombre launch.json e ingresa el siguiente código

{
    "configurations": [        
        {
            "name": "Iniciar Blazor",
            "type": "blazorwasm",
            "request": "launch",
            "preLaunchTask": "Compilar Blazor",
            "program": "${workspaceFolder}/BlazorWeb/bin/Debug/net8.0/BlazorWeb.dll", 
            "cwd": "${workspaceFolder}/BlazorWeb",
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            }
        },
        {
            "name": "Iniciar Web Api",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "Compilar WebApi",
            "program": "${workspaceFolder}/WebApi/bin/Debug/net8.0/WebApi.dll",
            "args": [],
            "cwd": "${workspaceFolder}/WebApi",
            "stopAtEntry": false,
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            }
        }
    ],
    "compounds": [
        {
            "name": "Iniciar Solución",
            "configurations": [
                "Iniciar Web Api",
                "Iniciar Blazor"
            ],
            "stopAll": true
        }
    ]
}

Una vez guardes ambos archivos, presiona F5 y verás que se lanzan dos navegadores, cada uno con un proyecto diferente.

Ahora, para conectar nuestro WebApi proyecto BlazorWeb modifica el archivo, como se indica

Program.cs

//Cambia esta linea, se documenta porque ya no es necesaria
//builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("builder.HostEnvironment.BaseAddress") });

//Por esta linea
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("https://localhost:7140/") });

La línea que se agrega toma la URL del WebApi, al ejecutar el proyecto con F5 verás que se inician dos navegadores, toma la URL del navegador donde se ejecuta el WebAPI ¿lo encuentras? Déjame saber si existe algún problema.

Ahora debemos agregar un nuevo componente razor al proyecto, crea en la carpeta Pages y archivo llamado Estaciones.razor

@page "/estaciones"

@using Modelos

@inject HttpClient Http

<h3>Estaciones</h3>

@if (estaciones == null)
{
    <p><em>Cargando...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Id</th>
                <th>Dirección</th>
                <th>¿Esta Abierta?</th> 
            </tr>
        </thead>
        <tbody>
            @foreach (var estacion in estaciones)
            {
                <tr>
                    <td>@estacion.EstacionDeServicioId</td>
                    <td>@estacion.Direccion</td>
                    <td>@estacion.EstaAbierta</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private EstacionDeServicio[]? estaciones;

    protected override async Task OnInitializedAsync()
    {
        estaciones = await Http.GetFromJsonAsync<EstacionDeServicio[]>("/estaciones");
    }
}

Este código es una mezcla de HTML y .NET, permitiendo interactuar con código C# en las diferentes vistas.

Este proyecto va a cambiar con el tiempo, buscaremos integrar mapas para ver las estaciones de servicio más cercana, reportar los precios de manera colaborativa, etc.

Por ahora mi interés principal es que llegues hasta acá con el proyecto funcionando, ¿como vamos?

Déjame saber si existe alguna duda y preparémonos para integrar un App Móvil.