Un petit exemple d'utilisation des événements envoyés par le serveur HTML dans une API Web principale ASP.Net.
L'application est un compteur qui augmente automatiquement chaque seconde. L'utilisateur peut mettre en pause ou reprendre le compteur, ou le régler sur une valeur donnée.
Le compteur est stocké en mémoire sur le serveur. Les modifications apportées à une session de navigateur seront propagées à toutes les autres sessions ouvertes.
Server Sent Events est une API Web qui vous permet de transmettre des messages d'un serveur vers JavaScript à l'aide de flux HTTP.
Ce n’est pas le seul moyen de transmettre des messages depuis un serveur, mais c’est certainement un moyen simple et aussi assez élégant.
Le code Javascript qui consomme les événements envoyés par le serveur se trouve dans le fichier stream.js et se présente comme suit :
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;
}
}
Ce référentiel contient une petite application Web autonome qui peut être utilisée comme référence ou comme code passe-partout, pour utiliser les événements envoyés par le serveur avec le backend ASP.Net Core.
L'implémentation du point de terminaison de streaming HTTP se trouve dans CounterController.cs et se présente comme suit. Il est adapté de cette réponse StackOverflow.
[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();
}
}
L'état (compteur) est stocké dans le service singleton PersistentCounter.
Le service déclenche un événement à chaque fois que la valeur du compteur est mise à jour. Le contrôleur s'abonne à cet événement et transmet la nouvelle valeur au client après chaque modification.
Pour exécuter l'application, tapez simplement les commandes suivantes dans le dossier principal du référentiel :
dotnet build
dotnet run
Assurez-vous d'avoir installé le SDK .NET 5 auparavant.
Ouvrez un navigateur et accédez à https://localhost:5001
.
Vous obtiendrez une erreur de certificat, car je n'utilise pas de certificat enregistré valide.
Ce qui suit ne sont que quelques informations générales qui fournissent un certain contexte. Vous n'avez pas besoin de le lire pour comprendre le code.
Ce référentiel est une petite partie d'une preuve de concept sur la façon de porter une application de bureau existante vers une application Web.
Utiliser ASP.Net pour le frontend serait probablement le moyen le plus simple de le faire. Cependant, j'aime beaucoup React/Redux pour le développement Web et j'y suis également plus expérimenté qu'avec ASP. J'ai donc décidé d'utiliser ASP pour le backend REST et d'utiliser React pour le frontend.
L'application Idiomatic .Net utilise énormément le modèle d'événement.
Mon idée est d'écrire une sorte de middleware, qui s'abonne à tous les événements produits dans l'application, les sérialise en JSON et les transmet au client à l'aide de Server Sent Events .
Le client réagira aux événements en envoyant des actions Redux, qui mettront à jour l'état du frontend.
Le backend exposera les points de terminaison REST pour toutes les autres interactions avec le frontend. Rien de spécial à cela.
Le middleware jouera le même rôle que le service singleton PersistentCounter dans ce référentiel.
Ce référentiel utilise uniquement du JavaScript simple. Pas de React ou Redux. Mon objectif ici est uniquement d'évaluer le transfert de messages via des flux HTTP. Le frontend n'est pas pertinent.