Announcing SignalR (alpha) for ASP.NET Core 2.0
NOTE: This is a post about the Alpha version of SignalR which has since been replaced with a new preview: https://blogs.msdn.microsoft.com/webdev/2018/02/27/asp-net-core-2-1-0-preview1-getting-started-with-signalr/
SignalR for ASP.NET Core is a rewrite of the original SignalR. We looked at common SignalR usage patterns and issues that users face today and decided that rewriting SignalR is the right choice. The new SignalR is simpler, more reliable, and easier to use. Despite these underlying changes, we’ve worked to ensure that the user-facing APIs are very similar to previous versions.
The client is distributed as an npm module that contains the Node.js version of the client (usable via require), as well as a version for use in the browser which can be included using a tag. TypeScript declarations for the client included in the module make it easy to consume the client from TypeScript applications.
Support for Binary Protocols
SignalR for ASP.NET Core offers two built-in hub protocols – a text protocol based on JSON and a binary protocol based on MessagePack. Messages using the MessagePack protocol are typically smaller than messages using the JSON protocol. For example a hub method returning the integer value of 1 will be 43 bytes when using the JSON based protocol while only 16 bytes when using MessagePack. (Note, the difference in size may vary depending on the message type, the contents of the message and the transport used – binary messages sent over Server Sent Events transport will be base64 encoded since Server Sent Events is a text transport.)
Support for Custom Protocols
The SignalR hub protocol is documented on GitHub and now has extension points that make it possible to plug in custom implementations.
It is now possible to stream data from the server to the client. Unlike a regular Hub method invocation, streaming means the server is able to send results to the client before the invocation completes.
Using SignalR with Bare Websockets
The process of connecting to SignalR has been simplified to the point where, when using websockets, it is now possible to connect to the server without any client with a single request.
Simplified Scale-Out Model
Unfortunately, when it comes to scaling out applications there is no “one size fits all” model – each application is different and has different requirements that need to be considered when scaling out the application. We have worked to improve, and simplify, the scale-out model and are providing a Redis based scale-out component in this Alpha. Support for other providers is being evaluated for the final release, for example service bus.
We added a number of new features to SignalR for ASP.NET Core but we also decided to remove support for some of the existing features or change how they work. One of the consequences of this is that SignalR for ASP.NET Core is not compatible with previous versions of SignalR. This means that you cannot use the old server with the new clients or the old clients with the new server. Below are the features which have been removed or changed in the new version of SignalR.
Simplified Connection Model
In the existing version of SignalR the client would try starting a connection to the server, and if it failed it would try using a different transport. The client would fail starting the connection when it could not connect to the server with any of the available transports. This feature is no longer supported with the new SignalR.
Another functionality that is no longer supported is automatic reconnects. Previously SignalR would try to reconnect to the server if the connection was dropped. Now, if the client is disconnected the user must explicitly start a new connection if they want to reconnect. Note, that it was required even before – the client would stop its reconnect attempts if it could not reconnect successfully within the reconnect timeout. One more reason to remove automatic reconnects was a very high cost of storing messages sent to clients. The server would by default remember the last 1000 messages sent to a client so that it could replay messages the client missed when it was offline. Since each connection had its own buffer the memory footprint of storing these messages was very high.
Sticky Sessions Are Now Required
Because of how scale-out worked in the previous versions of SignalR, clients could reconnect and/or send messages to any server in the farm. Due to changes to the scale-out model, as well as not supporting reconnects, this is no longer supported. Now, once the client connects to the server it needs to interact with this server for the duration of the connection.
Single Hub per Connection
The new version of SignalR does not support having more than one Hub per connection. This results in a simplified client API, and makes it easier to apply Authentication policies and other Middleware to Hub connections. In addition subscribing to hub methods before the connection starts is no longer required.
The ability to pass arbitrary state between clients and the Hub (a.k.a. HubState) has been removed as well as the support for Progress messages. We also don’t create a counterpart of hub proxies at the moment.
Setting up SignalR is relatively easy. After you create an ASP.NET Core application you need to add a reference to the Microsoft.AspNetCore.SignalR package like this
and a hub class:
This hub contains a method which once invoked will invoke the Send method on each connected client.
After adding a Hub class you need to configure the server to pass requests sent to the chatend point to SignalR:
NOTE: This package was renamed in preview1 of SignalR, after this Alpha was announced. It is now signalr, not signalr-client.
then copy the signalr-client.js to your script folder and include on your page using the tag:
After you include the script you can start the connection and interact with the server like this:
To use the SignalR managed client you need to add a reference to the Microsoft.AspNetCore.SignalR.Client package:
Then you can invoke hub methods and receive invocations like this:
If you want to take advantage of streaming you need to create a hub method that returns either a ReadableChannel or an IObservable. Here is an example of a hub method streaming stock prices to the client from the StockTicker sample we ported from the old SignalR:
Each time the server sends a stream item the displayStock client function will be invoked.
Invoking a streaming hub method from a C# client and reading the items could look as follows:
Migrating from existing SignalR
We will be releasing a migrating from existing SignalR guide in the coming weeks.
This is an alpha release and there are a few issues we know about:
- Connections using the Server Sent Event transport may be disconnected after two minutes of inactivity if the server is running behind IIS
- The WebSockets transport will not work if the server hosting SignalR is running behind IIS on Windows 7 or Windows Server 2008 R2, due to limitations in IIS
- ServerSentEvents transport in the C# client can hang if the client is being closed while the data from the server is still being received
- Streaming invocations cannot be canceled by the client
- Generating a production build of an application using TypeScript client in angular-cli fails due to UglifyJS not supporting ES6. This issue can be worked around as described in this comment.
The long awaited version of SignalR for ASP.NET Core just shipped. Try it out and let us know what you think! You can provide feedback or let us know about bugs/issues here.