(FRONT) FRONT (2023)

[Angular mosaic 5] Net Core SignalR Client (ReactiveX/rxjs, Configure Angular injector, Abstract class, Inject SirnalR service, Configure SignalR hub - forbid Negotiation, setUp Transport, URL, LogLevel, Anon or AU socket connection), Configure server Hub (MapHub endpoint, WithOrigins on CORS-policy, LogLevel, JWT AU).

9.1 Net Core SignalR Client configure(ReactiveX/rxjs, Configure Angular injector, Abstract class, Inject SignalR service, Configure SignalR hub - forbid Negotiation, setUp Transport, URL, LogLevel, Anon or AU socket connection).

Configuring SignalR client started from select correct package from JS repository.



Than, if we want to inject SignalR service to any Angular component we need to configure DI container (injector). In order to do this we need to create abstract class (SignalRService) and realization (PrivateSignalRService)



But for create Abstract class we need to define SignalR event (because event is complex type composed from SignalEventType and TDataShape) and define Enum type of SignalR event (on my case I start from event type CONTAINER_STARTED).



Abstract class allow us inject SignalR service to any project place and subscribe to particular event with reading data.




   1:  import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
   2:  import { Subscription } from 'rxjs';
   3:  import { SignalRService } from '../signalr/abstract-service';
   4:  import { SignalEventType } from '../signalr/signal-event-type';
   5:   
   6:  @Component({
   7:    selector: 'app-notifications',
   8:    templateUrl: './notifications.component.html',
   9:    styleUrls: ['./notifications.component.css']
  10:  })
  11:  export class NotificationsComponent implements OnInit, OnDestroy {
  12:    subscription!: Subscription;
  13:    constructor(
  14:      private signal: SignalRService
  15:    ) {
  16:    }
  17:    ngOnInit(): void {
  18:      this.subscription = this.signal.getDataStream<string>(SignalEventType.CONTAINER_STARTED).subscribe(message => {
  19:        console.log(message.data);
  20:      })
  21:    }
  22:   
  23:    ngOnDestroy() {
  24:      this.subscription.unsubscribe();
  25:    }
  26:  }

And this is injectable SignalR service realization.



In this code you can see all key future of SignalR service :


   1:  import { Injectable } from '@angular/core';
   2:  import { HttpClient } from '@angular/common/http';
   3:  import { filter, Observable, Subject, tap } from 'rxjs';
   4:  import { SignalRService } from './abstract-service';
   5:  import { SignalEvent } from './signal-event';
   6:  import { SignalEventType } from './signal-event-type';
   7:  import { HttpTransportType, HubConnection, HubConnectionBuilder } from '@microsoft/signalr';
   8:  import { LogLevel } from '@microsoft/signalr/dist/esm/ILogger';
   9:  //import { environment } from './../../environments/environment';
  10:   
  11:  @Injectable()
  12:  export class PrivateSignalRService extends SignalRService {
  13:  
  14:    private _signalEvent: Subject<SignalEvent<any>>;
  15:    private _openConnection: boolean = false;
  16:    private _isInitializing: boolean = false;
  17:    private _hubConnection!: HubConnection;
  18:    private JWT: string = "eyJhbGciOiJIUzI1....jyuxrmWeuGqIoI";
  19:   
  20:    constructor() {
  21:      super();
  22:      this._signalEvent = new Subject<any>();
  23:      this._isInitializing = true;
  24:      this._initializeSignalR();
  25:   
  26:    }
  27:   
  28:    getDataStream<TDataShape>(...filterValues: SignalEventType[]): Observable<SignalEvent<TDataShape>> {
  29:      this._ensureConnection();
  30:      return this._signalEvent.asObservable().pipe(filter(event => filterValues.some(f => f === event.type)));
  31:    }
  32:   
  33:    private _ensureConnection() {
  34:      if (this._openConnection || this._isInitializing) return;
  35:      this._initializeSignalR();
  36:    }
  37:   
  38:    private _initializeSignalR() {
  39:      this._hubConnection = new HubConnectionBuilder()
  40:        .withUrl('http://localhost:7000/DockerEventsHub',
  41:          {
  42:            withCredentials: true,
  43:            accessTokenFactory: () => this.JWT,
  44:            skipNegotiation: true,
  45:            transport: HttpTransportType.WebSockets
  46:          })
  47:        .configureLogging(LogLevel.Debug)
  48:        .build();
  49:      this._hubConnection.start()
  50:        .then(_ => {
  51:          this._openConnection = true;
  52:          this._isInitializing = false;
  53:          this._setupSignalREvents()
  54:        })
  55:        .catch(error => {
  56:          console.warn(error);
  57:          this._hubConnection.stop().then(_ => {
  58:            this._openConnection = false;
  59:          })
  60:        });
  61:   
  62:    }
  63:   
  64:    private _setupSignalREvents() {
  65:      this._hubConnection.on('ContainerStart', (data) => {
  66:        this._onMessage({ type: SignalEventType.CONTAINER_STARTED, data })
  67:      })
  68:      this._hubConnection.on('OTHER', (data) => {
  69:        const { numbers } = data;
  70:        this._onMessage({ type: SignalEventType.OTHER, data: numbers })
  71:      })
  72:      this._hubConnection.onclose((e) => this._openConnection = false);
  73:    }
  74:   
  75:    private _onMessage<TDataShape>(payload: SignalEvent<TDataShape>) {
  76:      this._signalEvent.next(payload);
  77:    }
  78:   
  79:  }

We can also see another code template for working with SignalR client



9.2 SignalR Server configure (endpoints.MapHub, UseCors.WithOrigins, Jwt Client Validating, logging.AddFilter("Microsoft.AspNetCore.SignalR"), logging.AddFilter("Microsoft.AspNetCore.Http.Connections"), Desktop tester.

Now we can go to my Server part. Firstly we can look to my Server configuration.



Configuring server is not simple and fast procedure, in my case this was be this procedure.

But I want to emphasize a couple of points. As I mention early connection is possible on anonymous and with authenticated user.



And second point, Browser forbid SignalR connection if CORS policy on server configured without URL (look above to WithOrigins on CORS-policy).



And third point, we need very carefully bind server method to push data to browser and client subscription.



And finally notes. Before we connect Angular client we can check SignalR hub by more simple desktop client, you can use my for this purposes my Visual Studio project template https://marketplace.visualstudio.com/items?itemName=vb-net-com.SignalRConsoleTestApp

9.3 Magic result of correct Server and Client configured.



9.4 Common project magic.

This project use my service Monitoring docker events and common project magic is: when container in Linux machine started than browser intermediately receive container name.








Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
Link to this page: http://www.vb-net.com/AngularMosaic4/Index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>