https://d226lax1qjow5r.cloudfront.net/blog/blogposts/how-to-receive-an-sms-with-blazor-and-signalr/Blog_Blazor-SignalR_1200x600.png

Cómo recibir un SMS con Blazor y SignalR

Publicado el May 5, 2021

Tiempo de lectura: 9 minutos

Cuando se trata de administrar mensajes SMS con la API de mensajería de Vonagerecibir mensajes SMS entrantes es primordial. En este tutorial, exploraremos la recepción de mensajes SMS en nuestra aplicación y su envío a nuestro front-end en tiempo real utilizando Blazor y SignalR Core.

Ir directamente al código

Si quieres ir directamente al código, visita el repositorio de esta demo en GitHub.

Requisitos previos

  • Necesitarás una Account API de Vonage

  • Necesitará la última versión del .NET Core 3.1 SDK

  • Necesitarás Visual Studio 2019, Visual Studio para Mac o Visual Studio Code, yo usaré VS Code para esta demo.

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Crear la aplicación

Navega a un directorio donde quieras poner la carpeta del proyecto y ejecuta el siguiente comando en tu terminal.

dotnet new blazorserver -o ReceiveSmsBlazor

Una vez hecho esto, cd en la carpeta ReceiveSmsBlazor que hemos creado y ejecute code . para iniciar VS Code. También puede abrir el archivo ReceiveSmsBlazor.csproj en Visual Studio.

Instalar paquetes NuGet

Hay dos paquetes NuGet que vamos a necesitar para esta demostración.

  1. Vonage

  2. Microsoft.AspNetCore.SignalR.Client

Vuelve a tu consola y ejecútalo:

dotnet add package Microsoft.AspNetCore.SignalR.Client dotnet add package Vonage

Crear el SMS Hub

SignalR dispersa todos los mensajes a través de "hubs" centrales, que notifican a todos los clientes conectados a ellos cuando se produce un evento determinado; en este caso, los eventos que vamos a recibir son mensajes SMS entrantes.

Cree una carpeta llamada Hubs. En esa carpeta, crea un archivo llamado SmsHub.cs e importe signalR con using Microsoft.AspNetCore.SignalR; dentro del mismo. A continuación, crea una clase SmsHub dentro del espacio de nombres ReceiveSmsBlazor.Hubs así:

namespace ReceiveSmsBlazor.Hubs
{
    public class SmsHub : Hub
    {

    }
}

No es necesario añadir ningún código aquí; estaremos manejando esto desde fuera de esta clase, sólo tiene que estar aquí para que podamos hablar con todos los clientes del Hub.

Construir nuestro controlador

Necesitaremos crear un controlador de API. Este controlador es donde vamos a recibir nuestros webhooks de SMS entrantes de Vonage.

Cree una nueva carpeta en el nivel superior de nuestro proyecto llamada Controllersy añadir un nuevo archivo SmsController.cs a esta carpeta.

Abre SmsController.cs y añádele las siguientes sentencias using.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using Vonage.Messaging;
using System.IO;
using System.Threading.Tasks;
using ReceiveSmsBlazor.Hubs;

A continuación, cree una clase SmsController clase en el espacio de nombres ReceiveSmsBlazor.Controllers espacio de nombres extending Controller y anótala con un Route en api/[controller] y un atributo ApiController de la siguiente manera:

namespace ReceiveSmsBlazor.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SmsController : Controller
    {

    }
}

Inyectar el contexto SmsHub

Para acceder al SmsHub, inyectaremos su contexto en dependencia. Crearemos una IHubContext llamada HubContext en tu clase SmsController y añade un constructor que tome IHubContex como argumento, y asigna nuestra propiedad HubContext a ese valor.

IHubContext<SmsHub> HubContext { get; set; }

public SmsController(IHubContext<SmsHub> hubContext)
{
    HubContext = hubContext;
}

Añadir la acción Webhook de SMS entrantes

Ahora que tenemos nuestro Hub disponible, sólo tenemos que añadir un método para manejar el SMS entrante y enviarlo a nuestro cliente.

Añade un nuevo método asíncrono llamado InboundSms que devuelve un archivo Task. En este método vamos a leer el SMS en el cuerpo de la solicitud, a continuación, vamos a enviar un mensaje a todos los clientes conectados a nuestro SmsHub que contiene el mensaje entrante de Msisdn (el número desde el que se originó el mensaje) y . Text.

[HttpPost("[action]")]
public async Task<IActionResult> InboundSms()
{
    using (var reader = new StreamReader(Request.Body))
    {
        var json = await reader.ReadToEndAsync();
        var inbound = JsonConvert.DeserializeObject<InboundSms>(json);
        await HubContext.Clients.All.SendAsync("ReceiveMessage", inbound.Msisdn, inbound.Text);
    }
    return NoContent();
}

Si nos has seguido, la ruta tendrá el aspecto siguiente api/sms/inboundsms en nuestro servidor cuando se ejecute. Tenga esto en cuenta para más adelante porque esto va a ser donde estamos apuntando nuestros webhooks cuando estamos configurando nuestros webhooks.

Configurar el middleware en el inicio

Ya que estamos usando Controllers y SignalR, necesitamos asegurarnos de que configuramos el middleware. Abre Startup.cs y añade using Microsoft.AspNetCore.ResponseCompression; a la sección de importación. Luego suelta en el método ConfigureServices y añade lo siguiente.

services.AddSignalR();
services.AddResponseCompression(opts => {
    opts.MimeTypes = ResponseCompressionDefaults.MimeTypes
        .Concat(new []{"application/octet-stream"});
});

Este snippet añadirá SignalR y compresión de respuesta para SignalR a tu aplicación.

Añadir controlador y SmsHub

Lo siguiente que tenemos que hacer es decirle a nuestra aplicación que utilice nuestros controladores y nuestro SmsHub. Para ello, introducimos el método Configure en Startup.cs y añade la línea app.UseResponseCompression(); al principio del método. Luego, en el UseEndpoints delegado, añade endpoints.MapControllers(); y endpoints.MapHub("/smshub");. Cuando todo esté dicho y hecho, tu app.UseEndpoints debería tener este aspecto:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapBlazorHub();
    endpoints.MapHub<Hubs.SmsHub>("/smshub");
    endpoints.MapFallbackToPage("/_Host");
});

Añadir un frontend

Ahora que tenemos todo el material interno funcionando para gestionar los SMS entrantes y tenemos todos nuestros servicios y hubs preparados, lo último que tenemos que hacer es crear un frontend.

Si ejecutas dotnet run en su consola y abriera la aplicación en localhost:5001 verías la página genérica de inicio de blazor.

Generic BlazorGeneric Blazor

Si desea eliminar la barra de navegación en el lado sólo tienes que ir a Shared/MinLayout.razor y elimine el sidebar div.

Todo lo demás que necesitamos hacer está en Pages/index.razor así que adelante y abre ese archivo ahora.

Incorporación de dependencias

Elimine todo lo que esté por debajo de la línea 2 en index.razor ya que es sólo código genérico de hola mundo. Con eso hecho, vamos a importar nuestro cliente SignalR, inyectar un gestor de navegación, y declarar que vamos a implementar IDisposable para limpiar el centro SignalR cuando se termina.

@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager NavigationManager
@implements IDisposable

Añadir nuestra tabla de mensajes

Vamos a mostrar los mensajes entrantes en una Tabla. Sigamos adelante y agreguemos una tabla simple a nuestro archivo index.razor archivo. Añade el siguiente código razor.

<h1>Messages</h1>

<table class="table" id="messageList">
    <thead>
        <tr>
            <th>From Number</th>
            <th>Message</th>
        </tr>
        @foreach (var message in _messages)
        {
            <tr>
                <td>@message.FromNumber</td>
                <td>@message.Text</td>
            </tr>
        }
    </thead>

</table>

El foreach recorrerá la colección de nuestra página _messages y creará una nueva fila con los campos FromNumber y Text.

Gestión de mensajes entrantes

De vuelta en nuestro controlador, utilizamos la llamada await HubContext.Clients.All.SendAsync("ReceiveMessage", inbound.Msisdn, inbound.Text); para enviar los mensajes de entrada Msisdn y Text a todos los clientes conectados al hub de SMS. Ahora es el momento de conectarse a ese Hub. Voy a seguir adelante y le mostrará todo el @code blob y luego caminar a través de cómo funciona cada parte.

@code {
    private HubConnection _hubConnection;
    private List<Message> _messages = new List<Message>();
    private class Message
    {
        public string FromNumber { get; set; }
        public string Text { get; set; }
    }

    protected override async Task OnInitializedAsync()
    {
        _hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri("/SmsHub"))
            .Build();
        _hubConnection.On<string, string>("ReceiveMessage", (from, text) =>
        {
            var message = new Message { FromNumber = from, Text = text };
            _messages.Add(message);
            StateHasChanged();
        });
        await _hubConnection.StartAsync();
    }

    public bool IsConnected => _hubConnection.State == HubConnectionState.Connected;

    public void Dispose()
    {
        _ = _hubConnection.DisposeAsync();
    }
}

Declarar campos privados y clase de mensaje

El siguiente fragmento de código declara los campos privados del componente. Esa lista _messages lista es de donde vamos a sacar los mensajes.

private HubConnection _hubConnection;
private List<Message> _messages = new List<Message>();
private class Message
{
    public string FromNumber { get; set; }
    public string Text { get; set; }
}

OnInitializedAsync

Reemplazamos el método OnInitializedAsync que es el método que se invoca cuando se inicializa el componente. Este método inicializa el _hubConnection (la conexión a nuestro SmsHub). Luego registra un manejador para el ReceiveMessage que estamos invocando con nuestro SmsController. Así, cada vez que se produzca ese evento, este método se disparará, añadiremos el mensaje entrante a nuestra colección _messages y llamaremos a la función StateHasChanged para indicar al componente que debe volver a renderizar, lo que hará que nuestros mensajes se recarguen en directo. Por último, iniciamos _hubConnection.

Pruebas con Ngrok

Ahora que tenemos todo construido, podemos seguir adelante y hacer pruebas con ngrok. Ngrok nos permite crear un túnel a nuestro servidor desde nuestra máquina local. Si estás usando ngrok con IIS Express, te animo a que le eches un vistazo a nuestro explicación sobre el tema ya que hay consideraciones especiales. Para esta demostración, ya que estamos utilizando el CLI dotnet, no necesitamos preocuparnos por esto. Abra su Properties/launchSettings.json en el objeto profiles, el perfil con el nombre de tu aplicación va a ser usado cuando inicies. Comprueba el applicationUrlque normalmente apuntará a https://localhost:5001 y http://localhost:5000. Asegúrate de borrar el que no es SSL y luego ejecuta el siguiente comando en otra ventana del símbolo del sistema.

ngrok http 5000

Sustituya 5000 por el número de puerto que su aplicación vaya a ejecutar sin SSL.

Este comando construirá un túnel hacia ese puerto. Ahora puede ejecutar su aplicación utilizando el comando dotnet run comando. Comprueba tu consola ngrok; te dirá la URL de acceso público de tu aplicación.

ngrokngrok

En mi caso, apunta a http://09c1cd61e26e.ngrok.io/. Navegando a esa URL, puedo ver el frontend de mi aplicación.

frontendfrontend

Configure sus Webhooks

La ruta para los webhooks sms entrantes es /api/sms/inboundsms con nuestra URL ngrok como ruta base. Esto significa que la ruta completa va a ser algo parecido a http://09c1cd61e26e.ngrok.io/api/sms/inboundsms. Todo lo que tenemos que hacer ahora es navegar a nuestra página de configuración y establecer la URL de los mensajes entrantes a nuestra ruta, y establecer el método HTTP a POST-JSON. Haz clic en el botón Save Changes en la parte inferior, y listo.

SMS settingsSMS settings

Prueba

Para probar, todo lo que necesitamos hacer es enviar un mensaje de texto a un número de Vonage asociado con esta Account. Puedes encontrarlo en el panel en Numbers->Tu número.

Tendrá este aspecto después de recibir un mensaje.

Inbound MessageInbound Message

Conclusión

Eso es todo lo que se necesita para permitirnos ver los mensajes SMS que llegan a una aplicación en tiempo real. Está claro que combinando SignalR, Blazor y las API de Vonage, ¡podemos crear cosas geniales!

Recursos

Compartir:

https://a.storyblok.com/f/270183/384x384/73d57fd8eb/stevelorello.png
Steve LorelloAntiguos alumnos de Vonage

Antiguo desarrollador .NET Advocate @Vonage, ingeniero de software poliglota full-stack, AI/ML