Lab: Blazor und SignalR Chat

In dieser Programmierübung lernen sie die Bibliothek SignalR einzusetzen.

Dauer: 20 Minuten

Projektumgebung erstellen

Starten Sie Visual Studio 2022 und erstellen ein neues Projekt vom Typ Blazer Server App mit den Namen SignalRLab. Belassen sie alle anderen Einstellungen auf Standard.

Screenshot 2022-04-28 065017

Starten Sie das Blazor Projekt durch Drücken von F5 aus Visual Studio um die Funktion zu prüfen. Beenden sie dann wieder den Debugger.

SignalR Einbinden

Fügen Sie nun das nötige Paket hinzu und ergänzen die Konfiguration des ASP.NET Blazor Projektes. Im Visual Studio Hauptmenü den Punkt Projekt –Drop Down – Nugget Pakete verwalten.

Suchen Sie nach SignalR und wählen sie das Paket Microsoft.AspNetCore.SignalR.Client.

Screenshot 2022-04-28 065642

Wählen sie im Dialog rechts den Punkt installieren und nehmen die neueste Version 6x

Wenn Sie mit der Paketmanager Console aus Visual Studio vertraut sind, können Sie alternativ auch per Kommandozeilenkommando arbeiten mit folgendem Befehl

Install-Package Microsoft.AspNetCore.SignalR.Client -Version 6.0.4
 

Message Hub erstellen und einbinden

Um die Nachrichten von den Browser Clients empfangen und per Push weiterleiten zu können wird eine SignalR Hub Klasse und Logik benötigt. Erstellen Sie in Visual Studio im Blazor Projekt das Unterverzeichnis Hubs und legen dort eine neue C# Klasse ChatHub.cs an.

Screenshot 2022-04-28 073545

Im Code Editor wird von der Basis Klasse Hub geerbt, der Namespace Microsoft.AspNetCore.SignalR ergänzt und der Code wie folgt implementiert.

   1:   public async Task SendMessage(string user, string message)
   2:    {
   3:   await Clients.All.SendAsync("ReceiveMessage", user, message);
   4:   }

 

Als nächstes muss der SignalR Endpunkt in der ASP.NET Anwendung per Code konfiguriert werden. Dafür öffnen Sie die Datei program.cs im Visual Studio Projekt per Doppelklick. Ergänzen Zeile 2 und speichern ihre Arbeit.

   1:  app.MapBlazorHub();
   2:  app.MapHub<ChatHub>("/chathub");

User Interface kreieren

Öffnen Sie um Visual Studio Editor durch Doppelklick die Datei index.razor aus dem Pages Verzeichnisses des Blazor Projekts. Entfernen Sie allen Code ausschließlich Zeile 1

Screenshot 2022-04-28 070150

Es werden folgendes UI mit HTML und dem Bootstrap Framework 5 implementieren.

Screenshot 2022-04-28 070537

Rufen Sie deshalb die URL https://getbootstrap.com/docs/ auf.

Wählen Sie im Browser aus dem Menü links den Punkt Forms aus. Suchen Sie optisch passende Formular Elemente und kopieren Sie diese in den Editor der Datei index.razor.

Das Form Element wird in Blazor nicht benötigt und muss dabei ausgespart werden.

Für die Listendarstellung wechseln sie den Bereich im Browser durch Auswahl im linken Menü –Components und den Unterpunkt List Group.

Auch hier sichten Sie die Lösung und kopieren den HTML Code in die Datei index.razor der am besten passend erscheint um obiges Ergebnis zu erhalten.

Starten Sie das Blazor Projekt und editieren den HTML Code in Visual Studio so lange bis die Beschriftungen passen. Um die Änderungen auch im Browser zu erkennen drücken Sie das Hot Reload Symbol (Flammen) in der Debug Leiste von Visual Studio.

Screenshot 2022-04-28 071527 

Die Darstellung der Liste brauchen Sie noch nicht zu beachten.

Für die Logik in der HTML Sicht werden nun einige Variablen benötigt um das Binding korrekt deklarieren zu können.

Ergänzen Sie danach zunächst einen Code Block unterhalb des HTML Teils im Editor der Datei index.razor.

   1:  @code
   2:  {
   3:      public readonly record struct 
Message(string Sender, string Text, DateTime Send);
   4:      private List<Message> messages = new List<Message>();
   5:      private string? userInput;
   6:      private string? messageInput;
   7:  }

 

Nun können Sie in derselben Datei die Darstellung finalisieren. Zunächst der Teil des Eingabe Formulars. Die HTML-Sequenzen und CSS-Klassen müssen nicht exakt ident sein.

   1:  <div class="mb-3">
   2:      <label class="form-label">
   3:          User:</label>
   4:          <input @bind="userInput" class="form-control" />
   5:  </div>
   6:  <div class="mb-3">
   7:      <label  class="form-label">
   8:          Message:</label>
   9:          <input @bind="messageInput" size="50" class="form-control"/>
  10:  </div>
  11:  <button @onclick="Send" class="btn btn-secondary" 
disabled="@(!IsConnected)">Send</button>

Schließlich noch die Listendarstellung. Für den maximalen Lerneffekt wird empfohlen den Code zu tippen, von außen nach innen und sich dabei auch von IntelliSense unterstützen zu lassen. Also zuerst das UL-Element samt schließenden </ul>. Danach das foreach mit TAB. Danach das innere LI-Element komplett usw.

   1:  <ul id="messagesList" class="list-group">
   2:      @foreach (var message in messages)
   3:      {
   4:          <li class='list-group-item 
@(message.Sender==userInput?"":"text-end")'
>
   5:             <b>@message.Sender @message.Send.ToString("mm:ss")</b> 
   6:             <p>@message.Text</p>
   7:              </li>
   8:      }
   9:  </ul>

 

Sie können nun wieder das Projekt starten um Compiler Fehler auszuschließen, wenn sei eine Dummy Methode Send einfügen und die Variable IsConnected.

C# Code Logik implementieren

Zunächst wird per Visual Studio Editor in der c# Datei Index.razor unmittelbar nach der @Page Direktive eingefügt

   1:  @using Microsoft.AspNetCore.SignalR.Client
   2:  @inject NavigationManager NavigationManager
   3:  @implements IAsyncDisposable

Dann wird im @Code Block die Referenz auf das HubConnection Objekt referenziert, das Nachrichten Entgegen nimmt oder auch an den Hub senden kann,

  private HubConnection? hubConnection;

 
Nun wird das Init Event angelegt und mit Code ergänzt für Verbindungsaufbau und eingehende Nachrichten am Client.

   1:  protected override async Task OnInitializedAsync()
   2:      {
   3:          hubConnection = new HubConnectionBuilder()
   4:              .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"))
   5:              .Build();
   6:          hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
   7:          {
   8:              messages.Add(new Message(Sender:user,Text:message,DateTime.Now));
   9:              InvokeAsync(StateHasChanged);
  10:          });
  11:          await hubConnection.StartAsync();
  12:      }

Weiter geht es im Code Editor der Datei index.razor mit dem Event des Buttons um die Benutzereingabe zum SignalR Hub zu senden.

   1:  private async Task Send()
   2:  {
   3:  if (hubConnection is not null)
   4:    {
   5:    await hubConnection.SendAsync("SendMessage", userInput, messageInput);
   6:    }
   7:  }

Letztendlich noch der C# Code um den Connection Status zu verwalten und die Ressourcen aufzuräumen.

   1:  public bool IsConnected =>
   2:          hubConnection?.State == HubConnectionState.Connected;
   3:  public async ValueTask DisposeAsync()
   4:  {
   5:   if (hubConnection is not null)
   6:   {
   7:    await hubConnection.DisposeAsync();
   8:   }
   9:  }

Starten Sie das Projekt im Debugger per F5. Um die zweiseitige Chat Nachricht zu testen öffnen sie einen zweiten Tab im Browser und kopieren die Projekt URL rein

Screenshot 2022-04-28 081843

Kommentare sind geschlossen