SignalR 2
|
This section documents ASP.NET MVC 5.3.x, ASP.NET Web API 2.2, ASP.NET Web Pages 3, OWIN/Katana, SignalR 2,
and ASP.NET Identity 2 — all running on .NET Framework 4.8.1 — the This is not ASP.NET Core MVC. ASP.NET MVC 5 is the pre-Core, This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
This page documents SignalR 2 on .NET Framework 4.8.1 — not ASP.NET Core SignalR, a rewritten library with a different client protocol and hub API (see the comparison at the end of this page).
Hubs and persistent connections
SignalR 2 offers two abstraction levels: the low-level PersistentConnection (raw message send/receive,
rarely used directly) and the high-level Hub, which exposes server methods clients call directly (an
RPC-like model) and lets the server call back into client-side JavaScript/.NET methods:
public class ChatHub : Hub
{
public void Send(string user, string message)
=> Clients.All.receiveMessage(user, message); // calls a client-side "receiveMessage" function
}
Startup.MapSignalR()
SignalR 2 is OWIN-hosted (see Authentication,
Identity, and OWIN for the shared OWIN pipeline) even inside an otherwise System.Web-hosted MVC 5
application:
[assembly: OwinStartup(typeof(MyApp.Startup))]
namespace MyApp
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR(); // maps hubs at /signalr by default
}
}
}
Hub methods, Clients.All/Caller/Group/User, groups
public class ChatHub : Hub
{
public override Task OnConnected()
{
Clients.Caller.welcome("Connected!");
return base.OnConnected();
}
public Task JoinRoom(string room)
=> Groups.Add(Context.ConnectionId, room);
public Task SendToRoom(string room, string message)
=> Clients.Group(room).receiveMessage(Context.User.Identity.Name, message);
public Task SendToUser(string userId, string message)
=> Clients.User(userId).receiveMessage(message); // requires a configured IUserIdProvider
}
Clients.All broadcasts to every connected client; Clients.Caller targets only the invoking connection;
Clients.Group(name) targets connections added to a named group (Groups.Add/Groups.Remove, tracked
server-side, not persisted — groups must be rejoined in OnConnected after a reconnect); Clients.User(id)
targets all of one user’s connections (across tabs/devices) via IUserIdProvider.
The JavaScript client and the .NET client
// generated hub proxies (/signalr/hubs, auto-generated from server-side Hub classes)
var chat = $.connection.chatHub;
chat.client.receiveMessage = function (user, message) { appendMessage(user, message); };
$.connection.hub.start().done(function () {
chat.server.send("Alice", "Hello!");
});
// .NET client (Microsoft.AspNet.SignalR.Client) -- e.g. a WPF app or a service talking to a SignalR 2 server
var connection = new HubConnection("https://example.com/");
var chat = connection.CreateHubProxy("ChatHub");
chat.On<string, string>("receiveMessage", (user, message) => Console.WriteLine($"{user}: {message}"));
await connection.Start();
await chat.Invoke("Send", "Alice", "Hello!");
Transports and fallback
SignalR 2 auto-negotiates the best available transport and falls back automatically: WebSockets →
Server-Sent Events → Forever Frame (IE-only, a hidden iframe kept perpetually loading) → long
polling (the universal fallback — repeated short-lived HTTP requests). This negotiation is what let
SignalR 2 target IIS/System.Web environments and older browsers where WebSockets might be unavailable
(Windows Server versions without WebSocket support, corporate proxies that block Upgrade headers), at the cost
of client code that must tolerate any of the four.
Authorization on hubs
[Authorize]
public class ChatHub : Hub
{
[Authorize(Roles = "Support")]
public void BroadcastAlert(string message) => Clients.All.alert(message);
}
Microsoft.AspNet.SignalR’s `[Authorize] is a separate attribute from System.Web.Mvc.AuthorizeAttribute
(see Filters) but relies on the same IPrincipal/ClaimsPrincipal
established by the OWIN authentication middleware.
Scale-out backplanes
A single SignalR 2 server holds connections in memory, so scaling to multiple servers (a web farm) requires a
backplane to fan messages out across instances — Clients.All.someMethod(…) on one server must reach
clients connected to every other server:
// NuGet: Microsoft.AspNet.SignalR.SqlServer / .Redis / .ServiceBus
GlobalHost.DependencyResolver.UseSqlServer("Data Source=...;Initial Catalog=SignalR;Integrated Security=True");
// or: GlobalHost.DependencyResolver.UseRedis("server", 6379, "password", "signalr-app");
// or: GlobalHost.DependencyResolver.UseServiceBus(connectionString, "signalr-app");
SQL Server, Redis, and Azure Service Bus are the three officially supported backplanes; Redis is the most common choice for throughput-sensitive deployments.
How SignalR 2 differs from ASP.NET Core SignalR
| SignalR 2 | ASP.NET Core SignalR | |
|---|---|---|
Hosting |
OWIN, inside or alongside |
ASP.NET Core middleware ( |
Wire protocol |
SignalR 2’s own JSON protocol |
A newer protocol supporting JSON and MessagePack, with a documented spec |
Client generation |
|
No server-generated proxy; clients call
|
Strongly typed hubs |
Not built in |
|
Streaming |
Not supported |
|
Scale-out |
SQL Server / Redis / Azure Service Bus backplanes |
Redis backplane, or Azure SignalR Service |
See SignalR for ASP.NET Core SignalR, and Introduction to SignalR and the SignalR 2 documentation index for this page’s material.
Next: Authentication, Identity, and OWIN covers the OWIN pipeline SignalR 2 is hosted on in more depth.