📜 ⬆️ ⬇️

The first version of SignalR for ASP.Net Core 2.0 has been released.

Hi, Habr! On September 14, it was announced the release of the first version of SignalR for ASP.Net Core, in connection with which I decided to translate a note on this event, adding it a bit. The original note is available on the MSDN blog.


What's new?


SignalR for ASP.Net Core is a rewritten from scratch version of the original SignalR. The new SignalR is simpler, more reliable and easier to use. Despite these internal changes, we tried to make the library API closest to previous versions.


Javascript / typeScript client


SignalR for ASP.Net Core has a completely new JavaScript client. It is written using TypeScript and is no longer dependent on jQuery. The client can also be used from Node.js with a few additional dependencies.


The client is distributed as an npm module, which contains the Node.js version of the client (connects via require), and also the browser version, which can be embedded using the <script> . TypeScript header files built into the module make it easy to use a client from TypeScript applications.


The client supports the latest versions of Chrome, FireFox, Edge, Safari, Opera, and Internet Explorer from version 9 (but not all transport protocols are compatible with each of the browsers).


Binary protocol support


SignalR for ASP.Net Core offers two embedded protocols - text based on JSON and binary protocol based on MessagePack . Messages using the MessagePack protocol are usually smaller than the same messages in JSON. For example, a hub message containing an integer unit value will consume 43 bytes when using JSON and only 16 bytes in a MessagePack. (Note that the difference in size may vary depending on the type of message, its contents and the transport protocol used - binary messages sent via Server-Sent Events (SSE) will be encoded in base64, since SSE is a text transport).


Custom protocol support


The SignalR hub protocol is documented on GitHub and now contains extension points that allow you to connect custom implementations.


Streaming


Now it is possible to transfer data from the server to the client. Unlike normal hub method calls, streaming means that the server can send results to the client before the call ends.


Using SignalR with clean web sockets


The process of connecting to SignalR has been simplified to the moment when, in the case of using web sockets, it is possible to connect to the server using a single request without using a client.


Simplified horizontal scaling


Unfortunately, there is no “silver bullet” for horizontal scaling of applications - each application has its own requirements that must be considered when scaling. We have done some work to simplify horizontal scaling and provide a Redis-based horizontal scaling component in this alpha version. Support for other providers, for example, service bus, is being tested for the final release.


What changed?


We added a number of new features to SignalR for ASP.Net Core, but at the same time we decided to remove support for some existing or change their behavior, as a result of which the new version of SignalR is not compatible with previous ones. This means that you cannot use the old server with new clients or old clients with a new server. Below are the functions that were excluded or the behavior of which has changed in the new version.


Simplified Connection Model


In the existing version of SignalR, the client, in case of unsuccessful connection, tries to connect using another transport. The client will not establish a connection if it cannot connect to the server by any of the available transports. In the new version of SignalR, this functionality is no longer supported.


Also, automatic reconnection is no longer available. In the previous version, SignalR tried to restore the connection when the connection with the server was lost. Now, if the client has disconnected, the user needs to explicitly establish a new connection. It should be noted that this was required before - the client stopped trying to automatically restore the connection if it was not possible to restore it during a certain timeout. Another reason for getting rid of this functionality was the high cost of storing messages sent to clients. By default, the server saved the last 1000 messages, so that it could re-send them to the client with which the connection was lost. Since each connection had its own buffer, storing these messages caused high memory consumption.


Binding Sessions (Sticky Sessions)


Using the horizontal scaling approach of the previous version of SignalR, clients could reconnect or send messages to any server in the farm. Due to changes in this approach and the rejection of automatic reconnections, the client should exchange messages only with the server with which the connection was established.


One hub to connect


The new version of SignalR does not support the use of multiple hubs within the same connection. Thanks to this, a simplification of the client API was achieved and the application of additional authentication policies and other middleware to the hub connection was simplified. Also no longer required to subscribe to the methods of the hub before the start of the connection.


Other changes


The ability to transfer an arbitrary state between clients and the hub (HubState), as well as support for state messages (Progress messages) has been removed. Also in this version a replacement for the hub proxy was not added.


Beginning of work


Installing SignalR is relatively simple. After creating a new ASP.Net Core application, you need to add a dependency on the Microsoft.AspNetCore.SignalR nuget package as shown in the example


 <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.0.0-alpha1-final" /> </ItemGroup> <ItemGroup> <Folder Include="wwwroot\scripts\" /> </ItemGroup> </Project> 

and your hub class


 using System; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; namespace Sample { public class Chat : Hub { public Task Send(string message) { return Clients.All.InvokeAsync("Send", message); } } } 

This hub contains a method that, when called, will in turn call the Send method on each of the clients.


After adding the hub class, you need to configure the server to process the sent requests as follows


 using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; namespace Sample { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSignalR(); } public void Configure(IApplicationBuilder app) { app.UseSignalR(routes => { routes.MapHub<Chat>("chat"); }); } } } 

After setting the necessary settings, you can call the hub methods from clients and vice versa. To use the JavaScript client in the browser, you need to install an npm package containing the SignalR client with the following command
npm install @aspnet/signalr-client
Now you can copy signalr-client.js to the scripts folder of your project and connect it to the page


 <script src="scripts/signalr-client.min.js"></script> 

Connecting the script will allow you to start connecting to the server and exchange commands with it.


 let connection = new signalR.HubConnection('/chat'); connection.on('send', data => { console.log(data); }); connection.start() .then(() => connection.invoke('send', 'Hello')); 

To use the managed client, you need to add a link to the Microsoft.AspNetCore.SignalR.Client package


 <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="1.0.0-alpha1-final" /> </ItemGroup> </Project> 

after which it will be possible to access the methods of the hub and handle calls to client methods.


If you want to take advantage of streaming, you need to create a hub method that will return ReadableChannel<T> or IObservable<T> . The following is the hub method from the StockTimer example, which transmits the stock value in the stream


 public IObservable<Stock> StreamStocks() { return _stockTicker.StreamStocks(); } 

JavaScript code called by this method looks like this.


 function startStreaming() { connection.stream("StreamStocks").subscribe({ next: displayStocks, error: function (err) { logger.log(err); } }); } 

Each time a server sends a stream item, the displayStocks client method will be called.
The hub method call from C # code is as follows


 private async Task StartStreaming() { var channel = connection.Stream<Stock>("StreamStocks", CancellationToken.None); while (await channel.WaitToReadAsync()) { while (channel.TryRead(out var stock)) { Console.WriteLine($"{stock.Symbol} {stock.Price}"); } } } 

Transition from the existing version of SignalR


In the coming weeks, migration documentation from the previous version of SignalR will be released.


Known Issues



From the author of the translation


From myself I want to add a small example of using the TypeScript version of the client in the SPA application on Angular. After completing all the steps above in the Getting Started section, in the Angular component it is enough to import the HubConnection class and use its methods. In the base application example created using the dotnet new angular command, in the fetchdata.component.ts component I added the functionality of displaying the number of clicks from the counter component as follows


 import { Component, Inject } from '@angular/core'; import { Http } from '@angular/http'; import { HubConnection } from "@aspnet/signalr-client"; @Component({ selector: 'fetchdata', templateUrl: './fetchdata.component.html' }) export class FetchDataComponent { public forecasts: WeatherForecast[]; public count: number; private notificationHub: HubConnection; constructor(http: Http, @Inject('BASE_URL') baseUrl: string) { http.get(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => { this.forecasts = result.json() as WeatherForecast[]; }, error => console.error(error)); this.notificationHub = new HubConnection("/notifications"); this.notificationHub.on("send", (data) => { this.count = data; }); this.notificationHub.start(); } } 

The hub addresses specified in the constructor call must match the one specified in the Startup class of the ASP.Net Core application (in the example from the translation, this address is "chat"). The hub's Send method is called from the counter component as follows.


 this.notificationHub.invoke("send", this.currentCount); 

PS This is my first post and at the same time a translation, for this I ask for comments on its quality to send to me in BOS.


')

Source: https://habr.com/ru/post/338490/


All Articles