blazorblazor-server-side

How to tell when a user leaves the site with Blazor Server Side


Blazor server side is built on signalr, so I would assume that it knows when a user leaves the website (closes the connection). Is there any event raised that I can use to log this? Or any other way really!


Solution

  • I think this service can help you...

    public class CircuitHandlerService : CircuitHandler 
        {
            public ConcurrentDictionary<string, Circuit> Circuits { get; set; }
            public event EventHandler CircuitsChanged;
    
            protected virtual void OnCircuitsChanged()
            => CircuitsChanged?.Invoke(this, EventArgs.Empty);
    
            public CircuitHandlerService()
            {
                Circuits = new ConcurrentDictionary<string, Circuit>();
            }
    
            public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
            {
                Circuits[circuit.Id] = circuit;
                OnCircuitsChanged();
                return base.OnCircuitOpenedAsync(circuit, cancellationToken);
            }
    
            public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
            {
                Console.WriteLine("OnCircuitClosedAsync");
                Circuit circuitRemoved;
                Circuits.TryRemove(circuit.Id, out circuitRemoved);
                OnCircuitsChanged();
                return base.OnCircuitClosedAsync(circuit, cancellationToken);
            }
    
            public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
            {
                Console.WriteLine("OnConnectionDownAsync");
                return base.OnConnectionDownAsync(circuit, cancellationToken);
            }
    
            public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
            {
                return base.OnConnectionUpAsync(circuit, cancellationToken);
            }
                   
        }
    

    Testing

    Index.razor

    @page "/"
    
    @using Microsoft.AspNetCore.Components.Server.Circuits
    @using BlazorCircuitHandler.Services
    
    @inject CircuitHandler circuitHandler
    @implements IDisposable
    
    
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <p>
        Number of Circuits: @((circuitHandler as <BlazorCircuitHandler is a name space in my app>.Services.CircuitHandlerService).Circuits.Count)
        <ul>
            @foreach (var circuit in (circuitHandler as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits)
            {
                <li>@circuit.Key</li>
            }
        </ul>
    </p>
    
    @code {
    
        protected override void OnInitialized()
        {
            (circuitHandler as CircuitHandlerService).CircuitsChanged += HandleCircuitsChanged;
            
        }
    
        public void Dispose()
        {
            
            (circuitHandler as CircuitHandlerService).CircuitsChanged -= HandleCircuitsChanged;
           
        }
    
        public void HandleCircuitsChanged(object sender, EventArgs args)
        {
            // notify the UI that the state has changed
              InvokeAsync(() => StateHasChanged());
        }
    }
    

    Startup.cs

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddRazorPages();
                services.AddServerSideBlazor();
    
                services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
            }
    

    Hope this helps...