Angular ist ein sehr beliebtes Framework für Web-Frontends von Google. Da SignalR für ASP.NET Core bereits einen TypeScript-Client mitbringt, lässt es sich sehr einfach in Kombination verwenden. In diesem Artikel wird eine Angular App für das Chat-Backend des letzten Artikels entwickelt.
Vorbedingungen
Folgendes muss vorab installiert sein:
- Das .NET Core SDK (>=2.0)
- Node.js und npm
Dieser Artikel setzt auf das Beispiel aus dem letzten Artikel auf.
Angular Projekt erzeugen
Zunächst erzeugen wir ein neues Angular Projekt. Hierzu verwenden wir Angular CLI. Dieses wird in einem Konsolenfenster über folgenden Befehl installiert:
> npm install -g @angular/cli
Daraufhin können wir ein einfaches Angular Projekt erzeugen, indem wir im Projektverzeichnis den folgenden Befehl ausführen:
> ng new angular-chat
Der Vorgang kann etwas länger dauern, weil die nötigen JavaScript Pakete automatisch heruntergeladen und installiert werden. Wenn der Vorgang erfolgreich beendet wurde, öffnen wir die Datei app.module.ts und fügen das FormsModule hinzu (Zeilen 3 und 13):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Durch das FormsModule wird der App ermöglicht, eine Datenbindung auf Formularelementen zu verwenden (das benötigen wir später).
SignalR Clientbibliothek installieren
Jetzt installieren wir den SignalR-Client über den Node Paketmanager. Hierzu wird folgender Befehl im Projektverzeichnis in einer Konsole ausgeführt:
> npm install @aspnet/signalr-client --save
Angular Komponente hinzufügen
Nun können wir mit der eigentlichen Implementierung des Chat-Clients in Angular beginnen. Dazu erzeugen wir eine neue Komponente, indem wir folgenden Befehl in der Konsole, innerhalb des neu erzeugten Verzeichnisses angular-chat ausführen:
> ng g component chat
Angular CLI generiert daraufhin eine leere Komponente und ein HTML-Template. Der folgende Code wird in die neu erstellte Datei chat.component.ts eingefügt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import { Component, OnInit } from '@angular/core';
import { HubConnection } from '@aspnet/signalr-client';
@Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.css']
})
export class ChatComponent implements OnInit {
private hubConnection: HubConnection;
message = '';
messages = [];
constructor() {
}
ngOnInit() {
this.hubConnection = new HubConnection('/chat');
this.hubConnection.on('broadcast', (message: string) => {
this.messages.push(message);
});
this.hubConnection.start();
}
sendMessage(): void {
this.hubConnection.invoke('send', this.message);
this.message = '';
}
}
Im Event ngOnInit
wird zunächst eine HubConnection
auf dem Endpunkt /chat erzeugt, den wir im Backend definiert haben. Daraufhin wird das Ereignis broadcast
abonniert und ankommende Nachrichten werden in einer Liste messages
abgelegt. Ebenfalls wird eine Verbindung zum Hub gestartet.
Über die Methode sendMessage
kann eine Nachricht über die HubConnection
gesendet werden.
HTML-Template
Jetzt benötigen wir noch das HTML-Template. Hierzu fügen wir den folgenden Code der Datei chat.component.html ein:
1
2
3
4
5
6
7
<div>
<input type="text" id="message" />
<input type="button" id="send" value="Senden" (click)="sendMessage()" />
<ul id="messages">
<li *ngFor="let message of messages"></li>
</ul>
</div>
Die Schaltfläche zum Senden wird auf die Methode sendMessage
gebunden und die angekommenen Nachrichten werden in einer Listendarstellung angezeigt.
Damit die Komponente verwendet werden kann, muss sie noch in ein anderes Template eingebunden werden (z.B. in die app.component.html):
1
<app-chat></app-chat>
App erstellen und starten
Zunächst konfigurieren wir das Ausgabeverzeichnis des Angular-Builds auf das wwwroot Verzeichnis. Hierzu öffnen wir die Datei .angular-cli.json und ändern den Eintrag outDir auf ”../wwwroot”.
Um die Anwendung zu erstellen, öffnen wir eine Konsole im Verzeichnis angular-chat und führen den Befehl: ng build aus.
Der Server kann über den Befehl dotnet run im Hauptverzeichnis gestartet werden.
Tipp zum Debuggen
Zum Debuggen von Frontend und Backend in Kombination wird bei Angular Projekten häufig der Proxy von Webpacks Entwicklungsserver verwendet. Dieser lässt sich auch für SignalR verwenden, indem WebSocket-Verbindungen aktiviert werden.
1
2
3
4
5
6
[{
"context": ["/chat"],
"target": "http://localhost:5000",
"secure": false,
"ws": true
}]
Hier in dem Beispiel werden alle Anfragen an die Route /chat an Port 5000 weitergeleitet. Durch das Attribut ws: true
werden auch WebSocket-Verbindungen über den Proxy aktiviert.
Tipp zu dotnet Performance
Nach der Installation von Angular kann man einen deutlichen Performanceeinbruch beim Erstellprozess des ASP.NET Backends feststellen. Das liegt an den NodeJS Paketen im node_modules Ordner. Dieser sollte eigentlich bereits automatisch aus dem Build ausgeschlossen sein - ich vermute das ist zurzeit noch ein Bug im Buildprozess der dotnet CLI.
Das Problem lässt sich recht einfach lösen, indem folgende Zeilen in die die .csproj-Datei hinzugefügt werden:
1
2
3
<PropertyGroup>
<DefaultItemExcludes>node_modules/**;angular-client/**;.git/**;$(DefaultItemExcludes)</DefaultItemExcludes>
</PropertyGroup>
Dadurch werden alle Vorkommnisse des node_modules Ordners ignoriert und vom Build exkludiert. Auch werden alle Quelldateien des Angular-Clients exkludiert, die im fertig gebauten Projekt ebenfalls nicht benötigt werden.
Da ich häufig im Hauptverzeichnis ein Git-Projekt initialisiere, habe ich auch den Ordner .git hinzugefügt. Dieser führt ansonsten ebenfalls zu größeren Performanceeinbrüchen.
Beispielprojekt
Das Beispielprojekt ist hier auf GitHub zu finden.
Zusammenfassung
In diesem Artikel wurde das Chat-Beispiel aus dem letzten Artikel um ein Angular Frontend erweitert. Durch die bei SignalR mitgelieferten TypeScript Klassen integriert sich SignalR sehr gut in Angular Projekte. Auch das Debugging gestaltet sich über den Webpack Proxy als sehr einfach.