Home > Back-end >  How do I get a SignalR circuit ID for my Blazor page?
How do I get a SignalR circuit ID for my Blazor page?

Time:10-24

Using only Blazor pages, I haven't defined a Hub class (which I'm told is where the HubCallerContext instance exists to get my SignalR circuit ID), so I don't know where to get the SignalR circuit ID Blazor is using to talk to the client for page changes. Do I have to create a Hub class artificially, or is there another way to get this ID?

CodePudding user response:

You can get the id by creating a CircuitHandler.

This should be working, I guess ;)

CircuitHandlerService.cs

using Microsoft.AspNetCore.Components.Server.Circuits;
using System;
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 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)
      {
           Circuit circuitRemoved;
           Circuits.TryRemove(circuit.Id, out circuitRemoved);
           OnCircuitsChanged();
           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);
      }
   }
 }

Usage

@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.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()
   {
       // Subscribe to the event handler
    (circuitHandler as CircuitHandlerService).CircuitsChanged  = 
         HandleCircuitsChanged;
    
    }

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

 public void HandleCircuitsChanged(object sender, EventArgs args)
 {
    // notify the component that its state has changed 
    // Important: You must use InvokeAsync
    InvokeAsync(() => StateHasChanged());
 }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();

            services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
        }

Note: To verify that it is working run the app. Then open another two tabs. Now, close the first tab you open (left to right), then the second. Notice the display of the number of active circuits...

  • Related