Tutorial: Compilación de una aplicación de chat de Blazor Server
En este tutorial se muestra cómo crear y modificar una aplicación Blazor Server. Aprenderá a:
- Crear una sala de chat sencilla con la plantilla de la aplicación Blazor Server.
- Trabajar con componentes de Razor.
- Usar el control de eventos y el enlace de datos en los componentes de Razor.
- Implementar rápidamente en Azure App Service con Visual Studio.
- Migrar desde SignalR local a Azure SignalR Service.
¿Estás listo para empezar?
Requisitos previos
- Instalación del SDK para .NET Core 3.0 (Versión >= 3.0.100)
- Instalación de Visual Studio 2019 (Versión >= 16.3)
¿Tiene problemas? Cuéntenoslo.
Creación de una sala de chat local en una aplicación Blazor Server
A partir de Visual Studio 2019 versión 16.2.0, Azure SignalR Service está integrado en el proceso de publicación de aplicaciones web para que la administración de las dependencias entre la aplicación web y SignalR Service sea mucho más cómoda. Puede trabajar sin cambios de código al mismo tiempo:
- en una instancia local de SignalR, en un entorno de desarrollo local.
- en Azure SignalR Service para Azure App Service.
Cree una aplicación de chat de Blazor:
En Visual Studio, seleccione Crear un proyecto.
Seleccione Aplicación Blazor.
Asigne un nombre a la aplicación y elija una carpeta.
Seleccione la plantilla de Aplicación Blazor Server.
Nota
Asegúrese de que ya ha instalado el SDK de .NET Core 3.0 o posterior para que Visual Studio reconozca correctamente la plataforma de destino.
También puede crear un proyecto ejecutando el comando
dotnet new
en la CLI de .NET:dotnet new blazorserver -o BlazorChat
Agregue un nuevo archivo de C# denominado
BlazorChatSampleHub.cs
y cree una claseBlazorChatSampleHub
derivada de la claseHub
para la aplicación de chat. Para más información sobre la creación de centros, consulte Creación y uso de centros de conectividad.using System; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; namespace BlazorChat { public class BlazorChatSampleHub : Hub { public const string HubUrl = "/chat"; public async Task Broadcast(string username, string message) { await Clients.All.SendAsync("Broadcast", username, message); } public override Task OnConnectedAsync() { Console.WriteLine($"{Context.ConnectionId} connected"); return base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception e) { Console.WriteLine($"Disconnected {e?.Message} {Context.ConnectionId}"); await base.OnDisconnectedAsync(e); } } }
Agregue un punto de conexión para el centro de conectividad del método
Startup.Configure()
.app.UseEndpoints(endpoints => { endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); endpoints.MapHub<BlazorChatSampleHub>(BlazorChatSampleHub.HubUrl); });
Instale el paquete
Microsoft.AspNetCore.SignalR.Client
para usar el cliente de SignalR.dotnet add package Microsoft.AspNetCore.SignalR.Client --version 3.1.7
Para implementar el cliente de SignalR, cree un nuevo componente de Razor llamado
ChatRoom.razor
en la carpetaPages
. Use el archivo ChatRoom.razor o realice los pasos siguientes:Agregue la directiva
@page
y las instrucciones "using". Use la directiva@inject
para insertar el servicioNavigationManager
.@page "/chatroom" @inject NavigationManager navigationManager @using Microsoft.AspNetCore.SignalR.Client;
En la sección
@code
, agregue los siguientes miembros al nuevo cliente de SignalR para enviar y recibir mensajes.@code { // flag to indicate chat status private bool _isChatting = false; // name of the user who will be chatting private string _username; // on-screen message private string _message; // new message input private string _newMessage; // list of messages in chat private List<Message> _messages = new List<Message>(); private string _hubUrl; private HubConnection _hubConnection; public async Task Chat() { // check username is valid if (string.IsNullOrWhiteSpace(_username)) { _message = "Please enter a name"; return; }; try { // Start chatting and force refresh UI. _isChatting = true; await Task.Delay(1); // remove old messages if any _messages.Clear(); // Create the chat client string baseUrl = navigationManager.BaseUri; _hubUrl = baseUrl.TrimEnd('/') + BlazorChatSampleHub.HubUrl; _hubConnection = new HubConnectionBuilder() .WithUrl(_hubUrl) .Build(); _hubConnection.On<string, string>("Broadcast", BroadcastMessage); await _hubConnection.StartAsync(); await SendAsync($"[Notice] {_username} joined chat room."); } catch (Exception e) { _message = $"ERROR: Failed to start chat client: {e.Message}"; _isChatting = false; } } private void BroadcastMessage(string name, string message) { bool isMine = name.Equals(_username, StringComparison.OrdinalIgnoreCase); _messages.Add(new Message(name, message, isMine)); // Inform blazor the UI needs updating InvokeAsync(StateHasChanged); } private async Task DisconnectAsync() { if (_isChatting) { await SendAsync($"[Notice] {_username} left chat room."); await _hubConnection.StopAsync(); await _hubConnection.DisposeAsync(); _hubConnection = null; _isChatting = false; } } private async Task SendAsync(string message) { if (_isChatting && !string.IsNullOrWhiteSpace(message)) { await _hubConnection.SendAsync("Broadcast", _username, message); _newMessage = string.Empty; } } private class Message { public Message(string username, string body, bool mine) { Username = username; Body = body; Mine = mine; } public string Username { get; set; } public string Body { get; set; } public bool Mine { get; set; } public bool IsNotice => Body.StartsWith("[Notice]"); public string CSS => Mine ? "sent" : "received"; } }
Agregue el marcado de la interfaz de usuario antes de la sección
@code
para interactuar con el cliente de SignalR.<h1>Blazor SignalR Chat Sample</h1> <hr /> @if (!_isChatting) { <p> Enter your name to start chatting: </p> <input type="text" maxlength="32" @bind="@_username" /> <button type="button" @onclick="@Chat"><span class="oi oi-chat" aria-hidden="true"></span> Chat!</button> // Error messages @if (_message != null) { <div class="invalid-feedback">@_message</div> <small id="emailHelp" class="form-text text-muted">@_message</small> } } else { // banner to show current user <div class="alert alert-secondary mt-4" role="alert"> <span class="oi oi-person mr-2" aria-hidden="true"></span> <span>You are connected as <b>@_username</b></span> <button class="btn btn-sm btn-warning ml-md-auto" @onclick="@DisconnectAsync">Disconnect</button> </div> // display messages <div id="scrollbox"> @foreach (var item in _messages) { @if (item.IsNotice) { <div class="alert alert-info">@item.Body</div> } else { <div class="@item.CSS"> <div class="user">@item.Username</div> <div class="msg">@item.Body</div> </div> } } <hr /> <textarea class="input-lg" placeholder="enter your comment" @bind="@_newMessage"></textarea> <button class="btn btn-default" @onclick="@(() => SendAsync(_newMessage))">Send</button> </div> }
Actualice el componente
NavMenu.razor
para insertar un nuevo componenteNavLink
para vincularlo a la sala de chat enNavMenuCssClass
.<li class="nav-item px-3"> <NavLink class="nav-link" href="chatroom"> <span class="oi oi-chat" aria-hidden="true"></span> Chat room </NavLink> </li>
Agregue algunas clases CSS al archivo
site.css
para dar estilo a los elementos de la interfaz de usuario de la página de chat./* improved for chat text box */ textarea { border: 1px dashed #888; border-radius: 5px; width: 80%; overflow: auto; background: #f7f7f7 } /* improved for speech bubbles */ .received, .sent { position: relative; font-family: arial; font-size: 1.1em; border-radius: 10px; padding: 20px; margin-bottom: 20px; } .received:after, .sent:after { content: ''; border: 20px solid transparent; position: absolute; margin-top: -30px; } .sent { background: #03a9f4; color: #fff; margin-left: 10%; top: 50%; text-align: right; } .received { background: #4CAF50; color: #fff; margin-left: 10px; margin-right: 10%; } .sent:after { border-left-color: #03a9f4; border-right: 0; right: -20px; } .received:after { border-right-color: #4CAF50; border-left: 0; left: -20px; } /* div within bubble for name */ .user { font-size: 0.8em; font-weight: bold; color: #000; } .msg { /*display: inline;*/ }
Para ejecutar la aplicación, pulse F5. Ahora puede iniciar el chat:
¿Tiene problemas? Cuéntenoslo.
Publicar en Azure
Al implementar la aplicación Blazor en Azure App Service, se recomienda usar Azure SignalR Service. Azure SignalR Service permite escalar verticalmente una aplicación Blazor Server a un gran número de conexiones de SignalR simultáneas. Además, los centros de datos de alto rendimiento y alcance global de SignalR Service son de gran ayuda a la hora de reducir la latencia ocasionada por la geografía.
Importante
En una aplicación Blazor Server, los estados de la interfaz de usuario se mantienen en el lado del servidor, lo que significa que se requiere una sesión de servidor permanente para conservar el estado. Si hay un único servidor de aplicaciones, las sesiones permanentes se garantizan mediante diseño. Sin embargo, si hay varios servidores de aplicaciones en uso, la negociación del cliente y la conexión se pueden redirigir a distintos servidores, lo que puede provocar una administración de estado de la interfaz de usuario incoherente en una aplicación de Blazor. Por lo tanto, se recomienda habilitar las sesiones de servidor permanentes como se muestra en appsettings.json:
"Azure:SignalR:ServerStickyMode": "Required"
Haga clic con el botón derecho en el proyecto y vaya a Publicar. Use la configuración siguiente:
- Destino: Azure
- Destino específico: se admiten todos los tipos de Azure App Service.
- App Service: cree o seleccione la instancia de App Service.
Agregue la dependencia de Azure SignalR Service.
Después de crear el perfil de publicación, puede ver un mensaje de recomendación para agregar Azure SignalR Service en Dependencias del servicio. Seleccione Configurar para crear una nueva o seleccione una instancia de Azure SignalR Service existente en el panel.
La dependencia del servicio realiza las siguientes actividades para permitir que la aplicación cambie automáticamente a Azure SignalR Service cuando se ejecute en Azure:
- Actualizar
HostingStartupAssembly
para usar Azure SignalR Service. - Agregar la referencia del paquete NuGet de Azure SignalR Service.
- Actualizar las propiedades del perfil para guardar la configuración de dependencias.
- Configurar el almacén de secretos según su elección.
- Agregar la configuración de appsettings.json para que el destino de la aplicación sea Azure SignalR Service.
- Actualizar
Publique la aplicación.
La aplicación ya está lista para publicarla. Tras la finalización del proceso de publicación, la aplicación se inicia automáticamente en un explorador.
Nota
Puede que la aplicación necesite un tiempo para iniciarse debido a la latencia de inicio de la implementación de Azure App Service. Puede usar las herramientas del depurador del explorador (normalmente presionando F12) para asegurarse de que el tráfico se ha redirigido a Azure SignalR Service.
¿Tiene problemas? Cuéntenoslo.
Habilitación de Azure SignalR Service para el desarrollo local
Agregue una referencia al SDK de Azure SignalR mediante el comando siguiente.
dotnet add package Microsoft.Azure.SignalR
Agregue una llamada a
AddAzureSignalR()
enStartup.ConfigureServices()
, tal como se muestra en el ejemplo siguiente:public void ConfigureServices(IServiceCollection services) { ... services.AddSignalR().AddAzureSignalR(); ... }
Configure la cadena de conexión de Azure SignalR Service en appsettings.json o mediante la herramienta Administrador de secretos.
Nota
El paso 2 se puede reemplazar por la configuración de ensamblados de inicio de hospedaje para que usen el SDK de SignalR.
Agregue la configuración para activar Azure SignalR Service en appsettings.json:
"Azure": { "SignalR": { "Enabled": true, "ConnectionString": <your-connection-string> } }
Configure el ensamblado de inicio de hospedaje para que utilice el SDK de Azure SignalR. Edite launchSettings.json y agregue una configuración como la del ejemplo siguiente dentro de
environmentVariables
:"environmentVariables": { ..., "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.Azure.SignalR" }
¿Tiene problemas? Cuéntenoslo.
Limpieza de recursos
Para limpiar los recursos creados en este tutorial, elimine el grupo de recursos mediante Azure Portal.
Recursos adicionales
Pasos siguientes
En este tutorial, ha aprendido a:
- Crear una sala de chat sencilla con la plantilla de la aplicación Blazor Server.
- Trabajar con componentes de Razor.
- Usar el control de eventos y el enlace de datos en los componentes de Razor.
- Implementar rápidamente en Azure App Service con Visual Studio.
- Migrar desde SignalR local a Azure SignalR Service.
Más información sobre la alta disponibilidad: