Ein kleines Beispiel für die Verwendung von vom HTML-Server gesendeten Ereignissen in einer ASP.Net-Kern-Web-API.
Die Anwendung ist ein Zähler, der jede Sekunde automatisch erhöht wird. Der Benutzer kann den Zähler anhalten oder fortsetzen oder ihn auf einen bestimmten Wert setzen.
Der Zähler wird im Speicher auf dem Server gespeichert. Änderungen in einer Browsersitzung werden an alle anderen geöffneten Sitzungen weitergegeben.
Server Sent Events ist eine Web-API, die es Ihnen ermöglicht, Nachrichten von einem Server mithilfe von HTTP-Streams an JavaScript zu senden.
Dies ist nicht die einzige Möglichkeit, Nachrichten von einem Server zu übertragen, aber es ist sicherlich eine einfache und auch recht elegante Möglichkeit.
Der Javascript-Code, der die vom Server gesendeten Ereignisse verarbeitet, befindet sich in der Datei stream.js und sieht wie folgt aus:
function readStream()
{
const evtSource = new EventSource('/Counter/Stream');
evtSource.onmessage = function(event) {
const el = document.getElementById('counter');
const { value } = JSON.parse(event.data);
el.textContent = value;
}
}
Dieses Repository enthält eine kleine eigenständige Webanwendung, die als Referenz oder als Boilerplate-Code für die Verwendung vom Server gesendeter Ereignisse mit dem ASP.Net Core-Backend verwendet werden kann.
Die Implementierung des HTTP-Streaming-Endpunkts ist in CounterController.cs zu finden und sieht wie folgt aus. Es ist aus dieser StackOverflow-Antwort übernommen.
[HttpGet]
[Route("Stream")]
public async Task StreamCounter(CancellationToken cancellationToken)
{
_logger.LogInformation("Start counter streaming.");
Response.StatusCode = 200;
Response.Headers.Add("Content-Type", "text/event-stream");
_counter.CounterUpdated += StreamValue;
while (!cancellationToken.IsCancellationRequested) {
await Task.Delay(1000);
}
_counter.CounterUpdated -= StreamValue;
_logger.LogInformation("Stop counter streaming.");
async void StreamValue(object sender, int value)
{
var messageJson = JsonConvert.SerializeObject(_counter, _jsonSettings);
await Response.WriteAsync($"data:{messageJson}nn");
await Response.Body.FlushAsync();
}
}
Der Zustand (Zähler) wird im Singleton-Dienst PersistentCounter gespeichert.
Der Dienst löst jedes Mal ein Ereignis aus, wenn der Zählerwert aktualisiert wird. Der Controller abonniert dieses Ereignis und überträgt den neuen Wert nach jeder Änderung an den Client.
Um die Anwendung auszuführen, geben Sie einfach die folgenden Befehle in den Hauptordner des Repositorys ein:
dotnet build
dotnet run
Stellen Sie sicher, dass Sie zuvor das .NET 5 SDK installiert haben.
Öffnen Sie einen Browser und navigieren Sie zu https://localhost:5001
.
Sie erhalten eine Zertifikatsfehlermeldung, da ich kein gültiges registriertes Zertifikat verwende.
Im Folgenden finden Sie lediglich einige Hintergrundinformationen, die einen gewissen Kontext bieten. Sie müssen es nicht lesen, um den Code zu verstehen.
Dieses Repository ist ein kleiner Teil eines Machbarkeitsnachweises für die Portierung einer vorhandenen Desktopanwendung in eine Webanwendung.
Die Verwendung von ASP.Net für das Frontend wäre wahrscheinlich der einfachste Weg, dies zu tun. Allerdings gefällt mir React/Redux für die Webentwicklung sehr gut und ich habe damit auch mehr Erfahrung als mit ASP. Deshalb habe ich mich entschieden, ASP für das REST-Backend und React für das Frontend zu verwenden.
Idiomatische .Net-Anwendungen nutzen das Ereignismuster in großem Umfang.
Meine Idee ist es, eine Art Middleware zu schreiben, die alle in der Anwendung erzeugten Ereignisse abonniert, sie in JSON serialisiert und sie mithilfe von „Server Sent Events“ an den Client überträgt.
Der Client reagiert auf die Ereignisse, indem er einige Redux-Aktionen auslöst, die den Frontend-Status aktualisieren.
Das Backend stellt REST-Endpunkte für alle anderen Interaktionen mit dem Frontend bereit. Daran ist nichts Besonderes.
Die Middleware spielt in diesem Repository dieselbe Rolle wie der Singleton-Dienst PersistentCounter.
Dieses Repository verwendet nur Plain-Vanilla-JavaScript. Kein React oder Redux. Mein Zweck besteht hier nur darin, das Senden von Nachrichten über HTTP-Streams auszuwerten. Das Frontend ist nicht relevant.