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

Comment recevoir un SMS avec Blazor et SignalR

Publié le May 5, 2021

Temps de lecture : 10 minutes

Lorsqu'il s'agit de gérer des messages SMS avec l Vonage Messaging APIde Vonage, la réception des SMS entrants est primordiale. Dans ce tutoriel, nous allons explorer la réception de messages SMS dans notre application et leur envoi vers notre front-end en temps réel en utilisant Blazor et SignalR Core.

Aller directement au code

Si vous souhaitez passer directement au code, il vous suffit de visiter le dépôt de cette démo sur GitHub.

Conditions préalables

  • Vous aurez besoin d'un compte API Vonage

  • Vous aurez besoin de la dernière version du NET Core 3.1 SDK

  • Vous aurez besoin soit de Visual Studio 2019, soit de Visual Studio pour Mac, soit de Visual Studio Code, j'utiliserai VS Code pour cette démo.

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.

Créer l'application

Naviguez jusqu'au répertoire où vous souhaitez placer le dossier du projet et exécutez la commande suivante dans votre terminal.

dotnet new blazorserver -o ReceiveSmsBlazor

Une fois que c'est fait, cd dans le dossier ReceiveSmsBlazor que nous avons créé et lancez code . pour lancer VS Code. Vous pouvez également ouvrir le fichier ReceiveSmsBlazor.csproj dans Visual Studio.

Installer les paquets NuGet

Il y a deux paquets NuGet dont nous allons avoir besoin pour cette démo.

  1. Vonage

  2. Microsoft.AspNetCore.SignalR.Client

Retournez à votre console et exécutez :

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

Créer le Hub SMS

SignalR diffuse tous les messages par l'intermédiaire de "hubs" centraux, qui notifient tous les clients qui y sont connectés lorsqu'un événement particulier se produit ; dans le cas présent, les événements que nous allons recevoir sont des SMS entrants.

Créez un dossier appelé Hubs. Dans ce dossier, créez un fichier appelé SmsHub.cs et importez le signalR avec using Microsoft.AspNetCore.SignalR; à l'intérieur de celui-ci. Ensuite, créez une classe SmsHub dans l'espace de noms ReceiveSmsBlazor.Hubs comme suit :

namespace ReceiveSmsBlazor.Hubs
{
    public class SmsHub : Hub
    {

    }
}

Vous n'avez pas besoin d'ajouter de code ici ; nous le piloterons depuis l'extérieur de cette classe, il a juste besoin d'être ici pour que nous puissions parler à tous les clients du Hub.

Construire notre contrôleur

Nous allons devoir créer un contrôleur API. C'est dans ce contrôleur que nous recevrons les webhooks SMS entrants de Vonage.

Créez un nouveau dossier au niveau supérieur de notre projet, appelé Controllerset ajoutez un nouveau fichier SmsController.cs à ce dossier.

Ouvrez SmsController.cs et ajoutez-y les instructions d'utilisation suivantes.

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

Ensuite, créez une classe SmsController dans l'espace de noms ReceiveSmsBlazor.Controllers étendant l'espace de noms Controller et l'annoter d'un Route à api/[controller] et un attribut ApiController comme suit :

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

    }
}

Injecter le contexte SmsHub

Pour accéder au SmsHub, nous allons injecter son contexte de dépendance. Créer une IHubContext appelée HubContext dans votre classe SmsController puis ajoutez un constructeur prenant un IHubContex comme argument, et assigner notre propriété HubContext à cette valeur.

IHubContext<SmsHub> HubContext { get; set; }

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

Ajouter l'action Webhook SMS entrant

Maintenant que nous avons notre Hub disponible, il nous suffit d'ajouter une méthode pour gérer le SMS entrant et l'envoyer à notre client.

Ajouter une nouvelle méthode asynchrone appelée InboundSms qui renvoie un Task. Dans cette méthode, nous allons lire le SMS dans le corps de la requête, puis nous allons envoyer un message à tous les clients connectés à notre SmsHub contenant le numéro de téléphone du message entrant (le numéro d'origine du message) et le numéro de téléphone du client (le numéro de téléphone du client). Msisdn (le numéro d'où provient le message) et 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 vous avez suivi, l'itinéraire ressemblera à api/sms/inboundsms sur notre serveur lorsqu'il sera lancé. Gardez cela à l'esprit pour plus tard, car c'est là que nous orienterons nos webhooks lorsque nous les configurerons.

Configuration de l'intergiciel au démarrage

Puisque nous utilisons des contrôleurs et SignalR, nous devons nous assurer que nous configurons l'intergiciel. Ouvrez Startup.cs et ajoutez using Microsoft.AspNetCore.ResponseCompression; dans la section d'importation. Ensuite, ajoutez à la méthode ConfigureServices et ajoutez ce qui suit.

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

Ce snippet ajoutera SignalR et la compression des réponses pour SignalR à votre application.

Ajouter un contrôleur et SmsHub

La prochaine chose à faire est d'indiquer à notre application d'utiliser nos contrôleurs et notre SmsHub. Déposez dans la méthode Configure dans Startup.cs et ajoutez la ligne app.UseResponseCompression(); au début de la méthode. Ensuite, dans le UseEndpoints ajouter endpoints.MapControllers(); et endpoints.MapHub("/smshub");. Lorsque tout est dit et fait, votre app.UseEndpoints devrait ressembler à ceci :

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

Ajouter un Frontend

Maintenant que tous les éléments internes fonctionnent pour gérer les SMS entrants et que nous avons mis en place tous nos services et hubs, la dernière chose à faire est de créer un frontend.

Si vous avez exécuté dotnet run dans votre console et que vous ouvriez l'application sur localhost:5001 vous verriez la page générique de démarrage de blazor.

Generic BlazorGeneric Blazor

Si vous souhaitez supprimer la barre de navigation sur le côté, il vous suffit d'aller dans la rubrique Shared/MinLayout.razor et de supprimer la sidebar div.

Tout ce que nous devons faire se trouve dans Pages/index.razor alors allez-y et ouvrez ce fichier maintenant.

Intégrer les dépendances

Supprimez tout ce qui se trouve en dessous de la ligne 2 dans index.razor car il s'agit simplement de code générique "hello world". Cela fait, importons notre client SignalR, injectons un gestionnaire de navigation et déclarons que nous implémenterons IDisposable pour nettoyer le hub SignalR lorsqu'il s'arrêtera.

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

Ajouter notre tableau des messages

Nous allons afficher les messages entrants dans un tableau. Allons-y et ajoutons un simple tableau dans notre fichier index.razor fichier. Ajoutez le code razor suivant.

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

La fonction foreach va parcourir en boucle la collection de notre page et créer une nouvelle ligne avec chaque message. _messages et créera une nouvelle ligne avec les informations suivantes pour chaque message FromNumber et Text.

Traiter les messages entrants

De retour dans notre contrôleur, nous avons utilisé l'appel await HubContext.Clients.All.SendAsync("ReceiveMessage", inbound.Msisdn, inbound.Text); pour envoyer les éléments Msisdn et Text à tous les clients connectés au hub SMS. Il est maintenant temps de se connecter à ce hub. Je vais aller de l'avant et vous montrer l'ensemble du @code blob et vous expliquer comment chaque partie fonctionne.

@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();
    }
}

Déclarer des champs privés et une classe de messages

Le bout de code suivant déclare les champs privés du composant. Cette _messages est l'endroit où nous allons récupérer les messages.

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

OnInitializedAsync

Nous surchargeons la méthode OnInitializedAsync Il s'agit de la méthode qui est invoquée lors de l'initialisation du composant. Cette méthode initialise la _hubConnection (la connexion à notre SmsHub). Elle enregistre ensuite un gestionnaire pour le ReceiveMessage que nous invoquons avec notre SmsController. Ainsi, chaque fois que cet événement se produit, cette méthode se déclenche, nous ajoutons le message entrant à notre collection _messages puis nous appellerons la fonction StateHasChanged pour indiquer au composant qu'il a besoin d'un nouveau rendu, ce qui permettra de recharger nos messages en direct. Enfin, nous lançons _hubConnection.

Tester avec Ngrok

Maintenant que nous avons tout construit, nous pouvons aller de l'avant et tester avec ngrok. Ngrok nous permet de créer un tunnel vers notre serveur depuis notre machine locale. Si vous utilisez ngrok avec IIS Express, je vous encourage à consulter notre explicatif sur le sujet car il y a des considérations particulières à prendre en compte. Pour cette démo, comme nous utilisons le CLI de dotnet, nous n'avons pas besoin de nous en préoccuper. Ouvrez votre fichier Properties/launchSettings.json dans l'objet profiles, le profil nommé après votre application sera utilisé au démarrage. Vérifiez l'élément applicationUrl; il pointera typiquement vers https://localhost:5001 et http://localhost:5000. Veillez à supprimer le profil non-SSL, puis exécutez la commande suivante dans une autre fenêtre d'invite de commande.

ngrok http 5000

Remplacez 5000 par le numéro de port de votre application qui fonctionnera sans SSL.

Cette commande créera un tunnel vers ce port. Vous pouvez maintenant exécuter votre application en utilisant la commande dotnet run pour lancer votre application. Vérifiez votre console ngrok ; elle vous indiquera l'URL publiquement accessible de votre application.

ngrokngrok

Dans mon cas, il pointe vers http://09c1cd61e26e.ngrok.io/. En naviguant vers cette URL, je peux voir le frontend de mon application.

frontendfrontend

Configurez vos Webhooks

La route pour les webhooks de sms entrants est /api/sms/inboundsms avec notre URL ngrok comme chemin de base. Cela signifie que la route complète sera à peu près la suivante http://09c1cd61e26e.ngrok.io/api/sms/inboundsms. Tout ce que nous avons à faire maintenant est de naviguer vers notre page des paramètres et de définir l'URL des messages entrants à notre route, et de définir la méthode HTTP à POST-JSON. Cliquez sur le bouton Save Changes en bas de la page, et nous sommes prêts à partir.

SMS settingsSMS settings

Test

Pour tester, il suffit d'envoyer un message texte à un numéro Vonage associé à ce compte. Ce numéro se trouve sur le tableau de bord sous numéros->Votre numéro.

Après la réception d'un message, l'écran se présente comme suit.

Inbound MessageInbound Message

Conclusion

C'est tout ce qu'il faut pour nous permettre de voir les SMS arriver dans une application en temps réel. Il est clair qu'en combinant SignalR, Blazor et les API de Vonage, nous pouvons créer des choses intéressantes !

Ressources

Partager:

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

Ancien développeur .NET Advocate @Vonage, ingénieur logiciel polyglotte full-stack, AI/ML