Web-Push mit SignalR

Ein Nachteil der Webtechnologie ist die Unmöglichkeit von serverinitiierten Nachrichten an den client. Aber jetzt nicht mehr. Es gibt eine Menge Techniken, wie man diesen Umstand bisher umgangen hat. Da wären (log-term) polling, Pulling (ständiges zyklisches Abfragen am Server) und viele weitere. Diese verursachen aber unnötigen Traffic und Last auf beiden Seiten. Eine sehr vielversprechende Technologie sind Websockets. Da Websockets aber noch nicht weit verbreitet sind (immerhin müssen die Webserver das Protokoll auch unterstützen), ist der Einsatz für öffentliche Bereiche noch nicht zu empfehlen. Und hier kommt SignalR ins Spiel.

SignalR ist eine asynchrone Benachrichtigungsbibliothek für das .Net Framework. Mit ihr kann man Echtzeitanwendungen für mehrere Benutzer im Web bauen. Und nun mal der Reihe nach.

SignalR besteht auf verschiedenen Paketen, welche über NuGet bezogen werden können. Notwendig für den Einsatz im Web sind SignalR.Hosting.AspNet und SignalR.Js. Beide werden über das Metapackage SignalR installiert. Desweiteren gibt es noch ein Package für Clients (WinForms/WPF/WP/etc) und für das DI-Framework Ninject und viele weitere kleine Helferlein.

Möchte man nun SignalR in einem Webprojekt einsetzen, reicht das Installieren vom Package SignalR. Dieses installiert neben den DLL’s (inkl. einer JSON-DLL) auch die JS-Datei in einer normalen und einer komprimierten Variante. Diese JS-Datei muss man in seine Webseite einbinden. Voraussetzung ist auch eine Version von jQuery ab 1.6. Um auch die Kommunikation zwischen Server und Client zu ermöglichen, muss man noch einen Platzhalter für eine dynamisch generierte Javascript-Datei einbinden. Diese Datei wird dann zur Laufzeit erzeugt und enthält Informationen aus dem Server (s.u.) Als Link gibt man „/signalr/hubs“ an.

<script src="@Url.Content("~/signalr/hubs")" type="text/javascript"></script>

Jetzt sind alle Vorbereitungen abgeschlossen und wir können uns an den internen Aufbau von SignalR machen.

Server

Die einfachste Art eine Kommunikation herzustellen, liegt in der Erzeugung eines Hubs. Ein Hub ist eine Art persistenter Verbindung zwischen Client und Server, welcher unterschiedliche Nachrichten empfangen und verarbeiten kann. Im Web legt man dazu einen Bereich an, wo man die Hub-Klassen implementiert. Bei MVC-Webs eignet sich ein Ordner „Hubs“. Die Klasse muss von SignalR.Hubs.Hub ableiten.

public class Chat : Hub
{
    public void Enter(string pseudonym)
    {
        Clients.addMessage(string.Format("{0} ist dem Chat beigetreten...", pseudonym));
    }

    public void Send(string message)
    {
        Clients.addMessage(message);
    }
}

Der hier gezeigte Hub kann zwei Nachrichten empfangen, Enter und Send. Beide übergeben einen String-Parameter. Im Hub hat man diverse Eigenschaften, um die Kommunikation durchzuführen.

Clients
Die Eigenschaft „Clients“ liegt als dynamischer Ausdruck vor und repräsentiert alle verbundenen Clients.

Caller
Auch die Eigenschaft „Caller“ ist ein dynamischer Ausdruck. Er repräsentiert nur den Aufrufer des Hubs, also nur einen bestimmten Client.

Context
Mit der Eigenschaft „Context“ kann man verschiedene Informationen zur Verbindung abfragen, wie Querystring, Cookies, User und die ID.

Wie im obigen Hub zu sehen, wird im dynamischen Objekt „Clients“ eine Methode addMessage(string) aufgerufen. Diese Methode gibt es serverseitig aber nicht, sondern muss im Client in JavaScript für SignalR erzeugt werden.

Client

In der Webseite fügt man nun den gewünschten HTML-Code und die notwendigen JS-Implementierungen ein. Ein Beispiel für einen Chat habe ich nachstehend aufgenommen.
Man benötigt eine Referenz des Serverhubs und kann darauf die Servermethoden aufrufen. Die im Hub aufgerufenen Methoden an Clients oder Caller werden als Callback darin definiert.

<h3>
    Chat</h3>
<div>
    Pseudonym:
    <input type="text" id="pseudonym" />
    <button id="enterChat">
        Beitreten</button>
</div>
<div style="border: solid 1px dimgray">
    <ul id="chat">
    </ul>
</div>
<div>
    Nachricht:
    <input type="text" id="message" />
    <input id="send" type="submit">
</div>
<script type="text/javascript">
    var active = false;
    var pseudonym;

    $(document).ready(function () {
        //Click-Handler zum Senden
        $("#send").click(function () {
            if (!active) {
                alert("Bitte erst dem Chat beitreten!");
                return;
            }

            chat.send(pseudonym + ": " + $('#message').val());
            $('#message').val("");
            $('#message').focus();
        });

        //Click-Handler zum Beitreten
        $("#enterChat").click(function () {
            pseudonym = $("#pseudonym").val();
            active = pseudonym != "";
            if (active)
                chat.enter(pseudonym);
        });

        //Server-Hub-Instanz wird referenziert 
        var chat = $.connection.chat;

        // client-side callback für Servermethode
        chat.addMessage = function (message) {
            $('#chat').append('<li>' + message + '</li>');
        };

        // Starten der Konversation
        $.connection.hub.start();
    });
</script>

Weitere Informationen und Beispiele gibt es im Wiki von SignalR.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s