web-dev-qa-db-fra.com

Comment puis-je appeler une méthode dans CircuitHandler de Blazor côté serveur?

Je crée une application de chat par Blazor côté serveur. Je souhaite afficher l'état en ligne de chaque utilisateur.

J'ai posé une question pour savoir comment obtenir l'événement lors de la fermeture de la page en Comment puis-je obtenir l'événement pendant la fermeture de la page côté serveur blazor?

Il semble maintenant que CircuitHandler soit le meilleur choix pour cela.

Lorsque l'utilisateur ferme la page, je souhaite définir un état utilisateur de en ligne à hors ligne dans la base de données. Et aussi, la clé primaire de chaque utilisateur est temporairement stockée dans le index.razor.

Mais maintenant, après l'exécution de OnCircuitClosedAsync(Circuit, CancellationToken), je ne sais pas comment invoquer une méthode pour y parvenir (je ne peux pas obtenir la variable du front-end Blazor ou appeler la méthode Blazor du front-end).

PS: Voici le code du back-end:

using Microsoft.AspNetCore.Components.Server.Circuits;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;


namespace BlazorCircuitHandler.Services
{
    public class CircuitHandlerService : CircuitHandler
    {
        public ConcurrentDictionary<string, Circuit> Circuits { get; set; }

        public CircuitHandlerService()
        {
            Circuits = new ConcurrentDictionary<string, Circuit>();
        }

        public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
        {
            Circuits[circuit.Id] = circuit;
            return base.OnCircuitOpenedAsync(circuit, cancellationToken);
        }

        public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
        {
            Circuit circuitRemoved;
            Circuits.TryRemove(circuit.Id, out circuitRemoved);
            return base.OnCircuitClosedAsync(circuit, cancellationToken);
        }

        public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
        {
            return base.OnConnectionDownAsync(circuit, cancellationToken);
        }

        public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
        {
            return base.OnConnectionUpAsync(circuit, cancellationToken);
        }
    }
}

Et voici le front-end:

@page "/"

@using Microsoft.AspNetCore.Components.Server.Circuits
@inject CircuitHandler CircuitHandlerService

<h1>Hello, world!</h1>

Welcome to your new app.

<p>
    Number of Circuits: @((CircuitHandlerService as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits.Count)

    <ul>
        @foreach (var circuit in (CircuitHandlerService as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits)
        {
            <li>@circuit.Key</li>            
        }
    </ul>
    @{ 
        var PrimaryKey = "abcdefg";
    }
</p>

Pourriez vous m'aider s'il vous plait? Je vous remercie.

6
Melon NG

Vous pouvez simplement exposer un événement dans votre gestionnaire de circuit:

public class CircuitHandlerService : CircuitHandler
{
    public event EventHandler CircuitsChanged;

    protected virtual void OnCircuitsChanged()
        => CircuitsChanged?.Invoke(this, EventArgs.Empty);

    public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        Circuits[circuit.Id] = circuit;
        OnCircuitsChanged();
        return Task.CompletedTask;
    }

    public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        Circuits.TryRemove(circuit.Id, out var circuitRemoved);
        OnCircuitsChanged();
        return Task.CompletedTask;
    }
}

Et puis, dans votre composant Razor, vous pouvez vous abonner à cet événement et actualiser l'interface utilisateur si nécessaire:

@implements IDisposable
@inject CircuitHandler circuitHandler

<ul>
    @foreach (var circuit in Circuits)
    {
        <li>@circuit.Key</li>
    }
</ul>

@code {
    private IDictionary<string, Circuit> Circuits
        => (circuitHandler as CircuitHandlerService).Circuits;

    protected override void OnInitialized()
    {
        // register event handler
        (circuitHandler as CircuitHandlerService).CircuitsChanged += HandleCircuitsChanged;
    }

    public void Dispose()
    {
        // unregister the event handler when the component is destroyed
        (circuitHandler as CircuitHandlerService).CircuitsChanged -= HandleCircuitsChanged;
    }

    public void HandleCircuitsChanged(object sender, EventArgs args)
    {
        // notify the UI that the state has changed
        StateHasChanged();
    }
}
0
poke