Inviare messaggi al client in real time tramite gli Hub di ASP.NET SignalR

di Marco De Sanctis, in ASP.NET 4.5, ASP.NET MVC, SignalR,

ASP.NET SignalR è una libreria open source che ci consente, con estrema semplicità, di aggiungere notifiche real time a una nostra applicazione, instaurando un canale di comunicazione bidirezionale e permanente tra server e client, così che possiamo utilizzarlo per inviare messaggi in entrambi i versi.

Come sappiamo, le specifiche di HTML5 hanno introdotto i WebSocket proprio per soddisfare questa specifica necessità; seppur supportati nativamente da ASP.NET 4.5 e dalle ultime versioni dei più diffusi browser, purtroppo richiedono la presenza di IIS 8 come server web e, specie se stiamo realizzando un sito destinato a un pubblico eterogeneo, non possiamo avere l'assoluta certezza che tutti i nostri visitatori siano compliant con questa tecnologia.

Esistono tuttavia altre tecniche per instaurare una canale di comunicazione full duplex, e il grande pregio di ASP.NET SignalR è proprio quello di astrarre questa problematica, impostando di volta in volta in automatico la connessione più idonea in base alle peculiarità del server e del client. Noi, come sviluppatori, non dobbiamo assolutamente preoccuparci di questi aspetti tecnici, e possiamo concentrarci sulle problematiche di business del prodotto che vogliamo realizzare.

Il nostro primo progetto

Immaginiamo di voler realizzare una semplice chat. Il primo passo è quello di aggiungere al progetto un nuovo oggetto di tipo SignalR Hub Class. Questa operazione include automaticamente i package NuGet necessari ad ASP.NET SignalR.


L'Hub è l'oggetto principale che utilizzeremo per interagire con i client: espone una serie di metodi che possono essere invocati da remoto (per esempio da un client JavaScript) e delle primitive tramite cui inviare dei messaggi a nostra volta. Il nostro ChatHub, nella fattispecie, contiene un metodo SendMessage tramite cui i client possono inviare un messaggio:

public class ChatHub : Hub
{
  public void SendMessage(string message)
  {
    Clients.All.newMessage(message);
  }
}

Questo metodo, a sua volta, deve girare il testo ricevuto a tutti i componenti della chat e, per farlo, può sfruttare la proprietà Clients; quest'oggetto è un HubConnectionContext, ossia il gateway tramite cui possiamo inviare messaggi dal server. Nel nostro caso specifico, abbiamo sfruttato la proprietà All, che rappresenta l'insieme di tutti i client collegati all'hub stesso, ma sono disponibili numerose altre modalità per individuare puntalmente i nostri destinatari:

  • All, come detto, individua tutti i client connessi;
  • Caller rappresenta il client chiamante;
  • Client invia un messaggio a un client dato il suo ConnectionID;
  • AllExcept invia un messaggio a tutti i client tranne che a quello specificato;
  • Others invia un messaggio a tutti i client, tranne che al chiamante;
  • Group e OtherInGroup individuano i destinatari in base ai gruppi; si tratta di una funzionalità di cui parleremo approfonditamente in un prossimo script.

Per esempio, se vogliamo inviare un messaggio a tutti i destinatari tranne che al chiamante, potremmo usare la proprietà Others o il metodo AllExcept, come nel codice seguente:

public void SendMessage(string message)
{
  // equivalente a
  //this.Clients.Others.newMessage(message);
  this.Clients.AllExcept(this.Context.ConnectionId).newMessage(message);
}

L'ultimo passo, prima di poter sfruttare il nostro hub, è quello di aggiungere le impostazioni di routing nella classe RouteConfig:

public class RouteConfig
{
  public static void RegisterRoutes(RouteCollection routes)
  {
    RouteTable.Routes.MapHubs();

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    // altre route...
  }
}

Questa istruzione aggiunge una route che, per default, risponde all'indirizzo ~/signalr/[nomeHub] e che costituisce un proxy JavaScript verso le funzionalità esposte dal nostro hub.

Il codice client side

A questo punto siamo pronti per realizzare il nostro primo client per ASP.NET SignalR, ossia una pagina (per esempio una view di un controller) che contenga i controlli di input necessari per l'inserimento del testo e il codice JavaScript per l'invio, oltre a un div da popolare con i messaggi ricevuti.

<div id="container">
    <input type="text" id="theMessage" />

    <input type="button" value="Send" id="btnSend" />
</div>

<div id="chatMessages"></div>

Lo script client di ASP.NET SignalR è contenuto nel package NuGet Microsoft.AspNet.SignalR.JS e va aggiunto tra i riferimenti in pagina unitamente a quello generato dal nostro hub di cui abbiamo parlato poc'anzi. Il contenuto della sezione scripts è simile a quello in basso:

@section scripts {
  <script src="~/Scripts/jquery.signalR-1.0.1.js" type="text/javascript"></script>
  <script src="~/signalr/hubs" type="text/javascript"></script>

  <script type="text/javascript">
    $(function () {
      // Invio messaggi
      $('#btnSend').click(function () {
        var text = $('#theMessage').val();

        if (text) {
          $.connection.chatHub.server.sendMessage(text);
        }
      });

      // Ricezione messaggi
      $.connection.chatHub.client.newMessage = function (message) {
        $("#chatMessages").append($('<p>' + message + '</p>'));
      };

      // Attivazione della connessione
      $.connection.hub.start();
    });
  </script>
}

L'interazione con l'hub server side è estremamente semplice e si basa sull'oggetto chatHub definito nel proxy e, in particolare, sui suoi field client e server: per inviare un messaggio, al click su btnSend, possiamo sfruttare la funzione server.sendMessage; la ricezione, invece, viene gestita associando una funzione di callback a newMessage, che nel nostro caso si occupa di accodare al div chatMessages il testo ricevuto.

Prima di poter procedere con l'invio, però, è necessario invocare la funzione hub.start, che si preoccuperà di negoziare con il server l'attivazione della connessione e di selezionare il protocollo di comunicazione più opportuno. Per esempio, se abbiamo a disposizione Windows 8 e IIS 8, visitando la pagina con Chrome, Firefox o Internet Explorer 10, ASP.NET SignalR sfrutterà WebSocket. Viceversa, su Internet Explorer 8 verrà utilizzato Forever Frame.

Per approfondimenti

Il nostro speciale Web Real Time
https://www.aspitalia.com/focuson/1300/Speciale-Web-Real-Time-WebSockets-SignalR.aspx
Comunicazione bidirezionale con WebSockets e HTML5
https://www.html5italia.com/script/68/Comunicazione-Bidirezionale-WebSockets-HTML5.aspx

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi