{"id":28440,"date":"2019-07-09T00:00:00","date_gmt":"2019-07-08T22:00:00","guid":{"rendered":"https:\/\/blexin.com\/?p=28440"},"modified":"2021-01-13T09:40:30","modified_gmt":"2021-01-13T08:40:30","slug":"applicazioni-real-time-con-signalr-asp-net-core-e-angular","status":"publish","type":"post","link":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/","title":{"rendered":"Applicazioni real-time con SignalR, ASP.NET Core e Angular"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" data-attachment-id=\"28441\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/attachment\/8db2df13-524e-4494-b65a-7caa972acced\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&amp;ssl=1\" data-orig-size=\"1024,608\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"8db2df13-524e-4494-b65a-7caa972acced\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?resize=1024%2C608&#038;ssl=1\" alt=\"\" class=\"wp-image-28441\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced-980x582.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced-480x285.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Supponiamo di voler creare un&#8217;applicazione web di monitoring, che fornisca all&#8217;utente una dashboard, in grado di visualizzare una serie di informazioni che si aggiornano nel tempo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Un primo approccio \u00e8 chiamare una API ciclicamente a determinati intervalli di tempo (<em>polling<\/em>) per aggiornare i dati sulla dashboard. C\u2019\u00e8 un problema per\u00f2: se non ci sono dati aggiornati stiamo inutilmente aumentando il traffico di rete con le nostre richieste. Un\u2019alternativa \u00e8 costituita dalla tecnica di&nbsp;<em>long-polling<\/em>: se il server non ha dati disponibili, invece di spedire una response vuota, pu\u00f2 tenere viva la richiesta finch\u00e9 non succeda qualcosa o si raggiunga un tempo prefissato di timeout. Se ci sono nuovi dati, la response completa giunge al client. Un approccio completamente diverso \u00e8 quello di invertire i ruoli: \u00e8 il backend a contattare i client quando i nuovi dati sono disponibili (push).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ricordiamo che HTML 5 ha standardizzato WebSocket, ossia una connessione permanente bidirezionale configurabile tramite un\u2019interfaccia Javascript nei browser compatibili. Purtroppo, deve esserci pieno supporto a WebSocket, sia lato client (browsers) che lato server, per renderlo disponibile. Dobbiamo, quindi, prevedere meccanismi alternativi (<em>fallback<\/em>) che consentano alla nostra applicazione di funzionare sempre e comunque.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft ha pubblicato nel 2013 una libreria open source chiamata&nbsp;<strong>SignalR<\/strong>&nbsp;per&nbsp;<strong>ASP.NET<\/strong>&nbsp;che nel 2018 \u00e8 stata riscritta per ASP.NET Core. SignalR astrae tutti i dettagli relativi ai meccanismi di comunicazione scegliendo il migliore tra quelli disponibili. Il risultato \u00e8 quello di poter scrivere codice come se ci trovassimo sempre in modalit\u00e0&nbsp;<em>push<\/em>. Con SignalR il server pu\u00f2 chiamare un metodo JavaScript su tutti i suoi client connessi, oppure su uno specifico.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Creiamo un progetto ASP.NET Core con template web-api, eliminando il controller di esempio che viene generato. Mediante NuGet, aggiungiamo\u00a0<em>Microsoft.AspNet.SignalR<\/em>\u00a0al progetto, in modo da poter creare un\u00a0<strong>Hub<\/strong>. L\u2019hub \u00e8 la pipeline ad alto livello, in grado di chiamare codice client inviando messaggi che contengono il nome e i parametri del metodo richiesto. Gli oggetti inviati come parametri vengono de-serializzati usando il protocollo opportuno. Il client cerca nel codice della pagina un metodo corrispondente al nome e, se lo trova, lo invoca passando come parametri i dati de-serializzati.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing Microsoft.AspNetCore.SignalR;\n\u00a0\nnamespace SignalR.Hubs\n{\n\u00a0\u00a0\u00a0\u00a0public class NotificationHub : Hub { }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Come probabilmente sapete, in ASP.NET Core la pipeline di gestione di una richiesta HTTP \u00e8 configurabile aggiungendo dei\u00a0<strong>middleware<\/strong>, che vanno a intercettare una richiesta, aggiungono la funzionalit\u00e0 configurata e la fanno proseguire al middleware successivo. Il middleware di SignalR deve essere preventivamente configurato aggiungendo nel metodo\u00a0<em>ConfigureServices<\/em>\u00a0della classe\u00a0<strong>Startup<\/strong>, l\u2019extension method\u00a0<em>services.AddSignalR()<\/em>. A questo punto, possiamo aggiungere il middleware alla pipeline, utilizzando l\u2019extension method\u00a0<em>app.UseSignalR()<\/em>\u00a0nel metodo\u00a0<em>Configure<\/em>\u00a0della classe Startup. Durante questa operazione, possiamo passare dei parametri di configurazione, tra cui la rotta del nostro hub:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\napp.UseSignalR(route =&gt;\n{\n\u00a0\u00a0\u00a0\u00a0route.MapHub&lt;notificationhub&gt;(&quot;\/notificationHub&quot;);\n})\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Uno scenario interessante, che ci permette di vedere anche un\u2019altra feature di ASP.NET Core, \u00e8 l\u2019<em>hosting<\/em>&nbsp;di un Hub SignalR nel contesto di un&nbsp;<strong>background worker<\/strong>&nbsp;process.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Immaginiamo di voler implementare il seguente caso d\u2019uso:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>eseguire della logica business<\/li><li>aspettare del tempo<\/li><li>decidere se fermarsi o ripetere il processo.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In ASP.NET Core, possiamo usare l\u2019interfaccia&nbsp;<em>IHostedService,<\/em>&nbsp;messa a disposizione dal framework, per implementare l\u2019esecuzione di processi in background in una applicazione .NET Core. I metodi da implementare sono&nbsp;<em>StartAsync()<\/em>&nbsp;e&nbsp;<em>StopAsync()<\/em>. Molto semplicemente, StartAsync \u00e8 invocato allo startup dell\u2019host, mentre StopAsync al suo shutdown.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aggiungiamo. quindi, al progetto una classe\u00a0<em>DashboardHostedService,<\/em>\u00a0che implementi\u00a0<em>IHostedService<\/em>. Aggiungiamo nel metodo\u00a0<em>ConfigureServices<\/em>\u00a0della classe Startup la registrazione dell\u2019interfaccia<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nservices.AddHostedService&lt;dashboardhostedservice&gt;();\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Nel costruttore della classe&nbsp;<em>DashboardHostedService,<\/em>&nbsp;iniettiamo&nbsp;<em>IHubContext<\/em>&nbsp;per accedere all\u2019hub aggiunto alla nostra applicazione.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nel metodo StartAsync, poi, impostiamo un timer, che ogni due secondi eseguir\u00e0 il codice contenuto nel metodo DoWork(). Tale metodo invia un messaggio contenente quattro stringhe, generate in maniera casuale.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ma a chi le trasmette? Nell\u2019esempio, stiamo inviando il messaggio a tutti i client connessi. Tuttavia, SignalR offre la possibilit\u00e0 di mandare messaggi a singoli utenti o a gruppi di utenti. In quest\u2019\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/core\/signalr\/groups?view=aspnetcore-2.2\">articolo<\/a>\u00a0trovate i dettagli che coinvolgono le funzionalit\u00e0 di autenticazione e autorizzazione in Asp.NET Core. \u00c8 interessante notare che un utente potrebbe essere collegato sia da un desktop, che da un telefono. Ciascun device avrebbe una connessione SignalR distinta, ma tutti e due sarebbero associati allo stesso utente.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing Microsoft.AspNetCore.SignalR;\nusing Microsoft.Extensions.Hosting;\nusing SignalR.Hubs;\nusing System;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\n\u00a0\nnamespace SignalR\n{\n\u00a0\u00a0\u00a0\u00a0public class DashboardHostedService: IHostedService\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private Timer _timer;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private readonly IHubContext&lt;notificationhub&gt; _hubContext;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public DashboardHostedService(IHubContext&lt;notificationhub&gt; hubContext)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_hubContext = hubContext;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Task StartAsync(CancellationToken cancellationToken)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_timer = new Timer(DoWork, null, TimeSpan.Zero,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TimeSpan.FromSeconds(2));\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Task.CompletedTask;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0private void DoWork(object state)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_hubContext.Clients.All.SendAsync(&quot;SendMessage&quot;, \n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val1 = getRandomString(),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val2 = getRandomString(),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val3 = getRandomString(),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0val4 = getRandomString()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0public Task StopAsync(CancellationToken cancellationToken)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_timer?.Change(Timeout.Infinite, 0);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return Task.CompletedTask;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Vediamo come gestire la parte client. Creiamo, ad esempio, un&#8217;applicazione Angular col comando&nbsp;<em>ng new SignalR<\/em>&nbsp;della Angular CLI. Installiamo il pacchetto node per SignalR (<em>npm i @aspnet\/signalr<\/em>). Aggiungiamo un service, che ci permetter\u00e0 di collegarci all\u2019hub creato in precedenza e di ricevere i messaggi.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ecco un primo possibile approccio, basato sulla restituzione, da parte del service nel metodo getMessage(), di un Observable&lt;Message>, mediante l\u2019uso di un Subject&lt;Message> dichiarato privatamente (Message \u00e8 una interface typescript, corrispondente all\u2019oggetto restituito dal backend):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n@Injectable({\n\u00a0providedIn: &#039;root&#039;\n})\nexport class SignalRService {\n\u00a0private message$: Subject&lt;message&gt;;\n\u00a0private connection: signalR.HubConnection;\n\u00a0\n\u00a0constructor() {\n\u00a0\u00a0\u00a0this.message$ = new Subject&lt;message&gt;();\n\u00a0\u00a0\u00a0this.connection = new signalR.HubConnectionBuilder()\n\u00a0\u00a0\u00a0.withUrl(environment.hubUrl)\n\u00a0\u00a0\u00a0.build();\n\u00a0\u00a0\u00a0this.connect();\n\u00a0}\n\u00a0private connect() {\n\u00a0\u00a0\u00a0this.connection.start().catch(err =&gt; console.log(err));\n\u00a0\u00a0\u00a0this.connection.on(&#039;SendMessage&#039;, (message) =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0this.message$.next(message);\n\u00a0\u00a0\u00a0});\n\u00a0}\n\u00a0public getMessage(): Observable&lt;message&gt; {\n\u00a0\u00a0\u00a0return this.message$.asObservable();\n\u00a0}\n\u00a0public disconnect() {\n\u00a0\u00a0\u00a0this.connection.stop();\n\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">All\u2019interno del constructor(), creiamo un oggetto di tipo signalR.HubConnection, che servir\u00e0 per connetterci al server. Ad esso, mediante il file environment.ts, passiamo la URL del nostro hub:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nthis.connection = new signalR.HubConnectionBuilder()\n\u00a0\u00a0\u00a0.withUrl(environment.hubUrl)\n\u00a0\u00a0\u00a0.build();\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Il constructor si occupa anche di invocare il metodo connect(), che effettua la connessione vera e propria, loggando eventuali errori in console.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nthis.connection.start().catch(err =&gt; console.log(err));\nthis.connection.on(&#039;SendMessage&#039;, (message) =&gt; {\n\u00a0\u00a0this.message$.next(message);\n});\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Un component che voglia mostrare i messaggi provenienti dal backend (dopo aver iniettato il servizio nel constructor), deve sottoscriversi al metodo getMessage() e gestire il messaggio arrivato. Nel caso di AppComponent, ad esempio:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n@Component({\n\u00a0selector: &#039;app-root&#039;,\n\u00a0templateUrl: &#039;.\/app.component.html&#039;,\n\u00a0styleUrls: &#x5B;&#039;.\/app.component.css&#039;]\n})\nexport class AppComponent implements OnDestroy {\n\u00a0private signalRSubscription: Subscription;\n\u00a0\n\u00a0public content: Message;\n\u00a0\n\u00a0constructor(private signalrService: SignalRService) {\n\u00a0\u00a0\u00a0this.signalRSubscription = this.signalrService.getMessage().subscribe(\n\u00a0\u00a0\u00a0\u00a0\u00a0(message) =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.content = message;\n\u00a0\u00a0\u00a0});\n\u00a0}\n\u00a0ngOnDestroy(): void {\n\u00a0\u00a0\u00a0this.signalrService.disconnect();\n\u00a0\u00a0\u00a0this.signalRSubscription.unsubscribe();\n\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">L\u2019utilizzo di un Subject &lt;Message> consente di gestire, in pi\u00f9 componenti contemporaneamente e indipendentemente, il Message restituito dall\u2019hub (sia per il subscribe che per l\u2019unsubscribe), ma bisogna evitare le insidie di un uso poco attento del Subject. Prendiamo in considerazione la seguente versione di getMessage():<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic getMessage(): Observable&lt;message&gt; {\n\u00a0\u00a0\u00a0return this.message$;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Ora il componente \u00e8 in grado di emettere anch\u2019esso un Message mediante questo semplice codice:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nconst produceMessage = this.signalrService.getMessage() as Subject&amp;lt;any&gt;;\n\u00a0produceMessage.next( {val1: &#039;a&#039;});\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Questo codice, invece, solleva un\u2019eccezione se il metodo getMessage() restituisce il Subject&lt;Message&gt; asObservable!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Un secondo approccio, pi\u00f9 semplice, che possiamo utilizzare nel caso un solo componente sia interessato a gestire i messaggi provenienti dal backend, \u00e8 il seguente:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n@Injectable({\n\u00a0providedIn: &#039;root&#039;\n})\nexport class SignalrService {\n\u00a0connection: signalR.HubConnection;\n\u00a0\n\u00a0constructor() {\n\u00a0\u00a0\u00a0this.connection = new signalR.HubConnectionBuilder()\n\u00a0\u00a0\u00a0.withUrl(environment.hubAddress)\n\u00a0\u00a0\u00a0.build();\n\u00a0\u00a0\u00a0this.connect();\n\u00a0}\n\u00a0\n\u00a0public connect() {\n\u00a0\u00a0\u00a0if (this.connection.state === signalR.HubConnectionState.Disconnected) {\n\u00a0\u00a0\u00a0\u00a0\u00a0this.connection.start().catch(err =&gt; console.log(err));\n\u00a0\u00a0\u00a0}\n\u00a0}\n\u00a0\n\u00a0public getMessage(next) {\n\u00a0\u00a0\u00a0\u00a0\u00a0this.connection.on(&#039;SendMessage&#039;, (message) =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0next(message);\n\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0}\n\u00a0\n\u00a0public disconnect() {\n\u00a0\u00a0\u00a0this.connection.stop();\n\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Al metodo getMessage, passiamo semplicemente la funzione di callback, che prender\u00e0 come argomento il message proveniente dal backend. In questo caso, AppComponent pu\u00f2 diventare:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic content: IMessage;\nconstructor(private signalrService: SignalrService) {\n\u00a0\u00a0\u00a0this.signalrService.getMessage(\n\u00a0\u00a0\u00a0\u00a0\u00a0(message: IMessage) =&gt; {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this.content = message;\n\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0);\n}\nngOnDestroy(): void {\n\u00a0\u00a0\u00a0this.signalrService.disconnect();\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Ultime righe di codice, rispettivamente in\u00a0<em>app.component.html<\/em>\u00a0e\u00a0<em>app.component.css,<\/em>\u00a0per dare un minimo di stile, e l&#8217;applicazione \u00e8 completata.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;div style=&quot;text-align:center&quot;&gt;\n\u00a0\u00a0&lt;h1&gt;\n\u00a0\u00a0\u00a0\u00a0DASHBOARD\n\u00a0\u00a0&lt;\/h1&gt;\n&lt;\/div&gt;\n&lt;div class=&quot;card-container&quot;&gt;\n\u00a0\u00a0&lt;div class=&quot;card&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;div class=&quot;container&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h4&gt;&lt;b&gt;Valore 1&lt;\/b&gt;&lt;\/h4&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;p&gt;{{content.val1}}&lt;\/p&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0&lt;div class=&quot;card&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;div class=&quot;container&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h4&gt;&lt;b&gt;Valore 2&lt;\/b&gt;&lt;\/h4&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;p&gt;{{content.val2}}&lt;\/p&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0&lt;div class=&quot;card&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;div class=&quot;container&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h4&gt;&lt;b&gt;Valore 3&lt;\/b&gt;&lt;\/h4&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;p&gt;{{content.val3}}&lt;\/p&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0&lt;div class=&quot;card&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;div class=&quot;container&quot;&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h4&gt;&lt;b&gt;Valore 4&lt;\/b&gt;&lt;\/h4&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;p&gt;{{content.val4}}&lt;\/p&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0&lt;\/div&gt;\n&lt;\/div&gt;\n\u00a0\n.card-container {\n\u00a0\u00a0display: flex;\n\u00a0\u00a0flex-wrap: wrap;\n}\n\u00a0\n.card {\n\u00a0\u00a0box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);\n\u00a0\u00a0transition: 0.3s;\n\u00a0\u00a0width: 40%;\n\u00a0\u00a0flex-grow: 1;\n\u00a0\u00a0margin: 10px;\n}\n\u00a0\n.card:hover {\n\u00a0\u00a0box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);\n}\n\u00a0\n.container {\n\u00a0\u00a0padding: 2px 16px;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Avviamo prima il backend e poi il frontend e controlliamo il risultato finale:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"229\" data-attachment-id=\"28447\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/attachment\/dashboard\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/dashboard.gif?fit=600%2C229&amp;ssl=1\" data-orig-size=\"600,229\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"dashboard\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/dashboard.gif?fit=600%2C229&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/dashboard.gif?resize=600%2C229&#038;ssl=1\" alt=\"\" class=\"wp-image-28447\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Sembra tutto ok! Trovate il codice qui:&nbsp;<a href=\"https:\/\/github.com\/AARNOLD87\/SignalRWithAngular\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/AARNOLD87\/SignalRWithAngular<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Al prossimo articolo!<\/p>\n\n\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Vediamo come inviare informazioni dal server al client utilizzando ASP.NET Core, SignalR e Angular<\/p>\n","protected":false},"author":196716245,"featured_media":28441,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"","_et_gb_content_width":"","_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_crdt_document":"","inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[688637374],"tags":[688637387,688637414],"class_list":["post-28440","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-angular","tag-asp-net-core"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Applicazioni real-time con SignalR, ASP.NET Core e Angular - Blexin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Applicazioni real-time con SignalR, ASP.NET Core e Angular - Blexin\" \/>\n<meta property=\"og:description\" content=\"Vediamo come inviare informazioni dal server al client utilizzando ASP.NET Core, SignalR e Angular\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"Blexin\" \/>\n<meta property=\"article:published_time\" content=\"2019-07-08T22:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-13T08:40:30+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"608\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Salvatore Sorrentino\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Salvatore Sorrentino\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/\"},\"author\":{\"name\":\"Salvatore Sorrentino\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/354db2bc97cac71c2ceeca21a92d5bed\"},\"headline\":\"Applicazioni real-time con SignalR, ASP.NET Core e Angular\",\"datePublished\":\"2019-07-08T22:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:30+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/\"},\"wordCount\":1077,\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1\",\"keywords\":[\"Angular\",\"Asp.net core\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/\",\"name\":\"Applicazioni real-time con SignalR, ASP.NET Core e Angular - Blexin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1\",\"datePublished\":\"2019-07-08T22:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:30+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/354db2bc97cac71c2ceeca21a92d5bed\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1\",\"width\":1024,\"height\":608},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blexin.com\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Applicazioni real-time con SignalR, ASP.NET Core e Angular\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/\",\"name\":\"Blexin\",\"description\":\"Con noi \u00e8 semplice\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blexin.com\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/354db2bc97cac71c2ceeca21a92d5bed\",\"name\":\"Salvatore Sorrentino\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a6ec0dc827d2acaa55df9dbf1007e23f6fcb8c9436df52ab48274bb2221085bf?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a6ec0dc827d2acaa55df9dbf1007e23f6fcb8c9436df52ab48274bb2221085bf?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a6ec0dc827d2acaa55df9dbf1007e23f6fcb8c9436df52ab48274bb2221085bf?s=96&d=identicon&r=g\",\"caption\":\"Salvatore Sorrentino\"},\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/author\\\/salvatore-sorrentinoblexin-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Applicazioni real-time con SignalR, ASP.NET Core e Angular - Blexin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/","og_locale":"it_IT","og_type":"article","og_title":"Applicazioni real-time con SignalR, ASP.NET Core e Angular - Blexin","og_description":"Vediamo come inviare informazioni dal server al client utilizzando ASP.NET Core, SignalR e Angular","og_url":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/","og_site_name":"Blexin","article_published_time":"2019-07-08T22:00:00+00:00","article_modified_time":"2021-01-13T08:40:30+00:00","og_image":[{"width":1024,"height":608,"url":"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1","type":"image\/png"}],"author":"Salvatore Sorrentino","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Salvatore Sorrentino","Tempo di lettura stimato":"8 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/#article","isPartOf":{"@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/"},"author":{"name":"Salvatore Sorrentino","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/354db2bc97cac71c2ceeca21a92d5bed"},"headline":"Applicazioni real-time con SignalR, ASP.NET Core e Angular","datePublished":"2019-07-08T22:00:00+00:00","dateModified":"2021-01-13T08:40:30+00:00","mainEntityOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/"},"wordCount":1077,"image":{"@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1","keywords":["Angular","Asp.net core"],"articleSection":["Blog"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/","url":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/","name":"Applicazioni real-time con SignalR, ASP.NET Core e Angular - Blexin","isPartOf":{"@id":"https:\/\/blexin.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/#primaryimage"},"image":{"@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1","datePublished":"2019-07-08T22:00:00+00:00","dateModified":"2021-01-13T08:40:30+00:00","author":{"@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/354db2bc97cac71c2ceeca21a92d5bed"},"breadcrumb":{"@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/#primaryimage","url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1","width":1024,"height":608},{"@type":"BreadcrumbList","@id":"https:\/\/blexin.com\/it\/blog\/applicazioni-real-time-con-signalr-asp-net-core-e-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blexin.com\/it\/"},{"@type":"ListItem","position":2,"name":"Applicazioni real-time con SignalR, ASP.NET Core e Angular"}]},{"@type":"WebSite","@id":"https:\/\/blexin.com\/it\/#website","url":"https:\/\/blexin.com\/it\/","name":"Blexin","description":"Con noi \u00e8 semplice","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blexin.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/354db2bc97cac71c2ceeca21a92d5bed","name":"Salvatore Sorrentino","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/a6ec0dc827d2acaa55df9dbf1007e23f6fcb8c9436df52ab48274bb2221085bf?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a6ec0dc827d2acaa55df9dbf1007e23f6fcb8c9436df52ab48274bb2221085bf?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a6ec0dc827d2acaa55df9dbf1007e23f6fcb8c9436df52ab48274bb2221085bf?s=96&d=identicon&r=g","caption":"Salvatore Sorrentino"},"url":"https:\/\/blexin.com\/it\/author\/salvatore-sorrentinoblexin-com\/"}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/8db2df13-524e-4494-b65a-7caa972acced.png?fit=1024%2C608&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/pcyUBx-7oI","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28440","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/users\/196716245"}],"replies":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/comments?post=28440"}],"version-history":[{"count":6,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28440\/revisions"}],"predecessor-version":[{"id":28450,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28440\/revisions\/28450"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media\/28441"}],"wp:attachment":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media?parent=28440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/categories?post=28440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/tags?post=28440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}