$npx -y skills add managedcode/dotnet-skills --skill signalrImplement or review SignalR hubs, streaming, reconnection, transport, and real-time delivery patterns in ASP.NET Core applications. USE FOR: building chat, notification, collaboration, or live-update features; debugging hub lifetime, connection state, or transport issues; decidin
| 1 | # SignalR |
| 2 | |
| 3 | ## Trigger On |
| 4 | |
| 5 | - building chat, notification, collaboration, or live-update features |
| 6 | - debugging hub lifetime, connection state, or transport issues |
| 7 | - deciding whether SignalR or another transport better fits the scenario |
| 8 | - implementing real-time broadcasting to groups of connected clients |
| 9 | - scaling SignalR across multiple servers |
| 10 | |
| 11 | ## Documentation |
| 12 | |
| 13 | - [ASP.NET Core SignalR Overview](https://learn.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-10.0) |
| 14 | - [SignalR Hubs](https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-10.0) |
| 15 | - [SignalR API Design Considerations](https://learn.microsoft.com/en-us/aspnet/core/signalr/api-design?view=aspnetcore-10.0) |
| 16 | - [SignalR Production Hosting and Scaling](https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-10.0) |
| 17 | - [SignalR Configuration](https://learn.microsoft.com/en-us/aspnet/core/signalr/configuration?view=aspnetcore-10.0) |
| 18 | |
| 19 | ### References |
| 20 | |
| 21 | - [patterns.md](references/patterns.md) - Detailed hub patterns, streaming, groups, presence, and advanced messaging techniques |
| 22 | - [anti-patterns.md](references/anti-patterns.md) - Common SignalR mistakes and how to avoid them |
| 23 | |
| 24 | ## Workflow |
| 25 | |
| 26 | 1. Use SignalR for broadcast-style or connection-oriented real-time features; do not force gRPC into hub-style fan-out scenarios. |
| 27 | 2. Model hub contracts intentionally and keep hub methods thin, delegating durable work elsewhere. |
| 28 | 3. Plan for reconnection, backpressure, auth, and fan-out costs instead of treating real-time messaging as stateless request/response. |
| 29 | 4. Use groups, presence, and connection metadata deliberately so scale-out behavior is understandable. |
| 30 | 5. If Native AOT or trimming is in play, validate supported protocols and serialization choices explicitly. |
| 31 | 6. Test connection behavior and failure modes, not just happy-path message delivery. |
| 32 | |
| 33 | ## Current Upstream Notes |
| 34 | |
| 35 | - `dotnet/aspnetcore` `v10.0.10` is a servicing release. Keep SignalR architecture guidance focused on hub contract design, reconnection, transport, authorization, and scale-out validation. |
| 36 | - The July 2026 ASP.NET Core overview still positions SignalR for real-time server/client communication. After servicing updates, rerun at least one reconnect and group-broadcast smoke path because dependency updates can expose client/server package mismatches. |
| 37 | |
| 38 | ## Hub Patterns |
| 39 | |
| 40 | ### Strongly-Typed Hub (Recommended) |
| 41 | ```csharp |
| 42 | // Define the client interface |
| 43 | public interface IChatClient |
| 44 | { |
| 45 | Task ReceiveMessage(string user, string message); |
| 46 | Task UserJoined(string user); |
| 47 | Task UserLeft(string user); |
| 48 | } |
| 49 | |
| 50 | // Implement the strongly-typed hub |
| 51 | public class ChatHub : Hub<IChatClient> |
| 52 | { |
| 53 | public async Task SendMessage(string user, string message) |
| 54 | { |
| 55 | // Compiler checks client method calls |
| 56 | await Clients.All.ReceiveMessage(user, message); |
| 57 | } |
| 58 | |
| 59 | public override async Task OnConnectedAsync() |
| 60 | { |
| 61 | await Clients.Others.UserJoined(Context.User?.Identity?.Name ?? "Anonymous"); |
| 62 | await base.OnConnectedAsync(); |
| 63 | } |
| 64 | |
| 65 | public override async Task OnDisconnectedAsync(Exception? exception) |
| 66 | { |
| 67 | await Clients.Others.UserLeft(Context.User?.Identity?.Name ?? "Anonymous"); |
| 68 | await base.OnDisconnectedAsync(exception); |
| 69 | } |
| 70 | } |
| 71 | ``` |
| 72 | |
| 73 | ### Using Groups for Targeted Messaging |
| 74 | ```csharp |
| 75 | public class NotificationHub : Hub<INotificationClient> |
| 76 | { |
| 77 | public async Task JoinGroup(string groupName) |
| 78 | { |
| 79 | await Groups.AddToGroupAsync(Context.ConnectionId, groupName); |
| 80 | await Clients.Group(groupName).UserJoined(Context.User?.Identity?.Name); |
| 81 | } |
| 82 | |
| 83 | public async Task LeaveGroup(string groupName) |
| 84 | { |
| 85 | await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName); |
| 86 | } |
| 87 | |
| 88 | public async Task SendToGroup(string groupName, string message) |
| 89 | { |
| 90 | await Clients.Group(groupName).ReceiveNotification(message); |
| 91 | } |
| 92 | } |
| 93 | ``` |
| 94 | |
| 95 | ### Hub Method with Custom Object Parameters (API Versioning) |
| 96 | ```csharp |
| 97 | // Use custom objects to avoid breaking changes |
| 98 | public class SendMessageRequest |
| 99 | { |
| 100 | public string Message { get; set; } = string.Empty; |
| 101 | public string? Recipient { get; set; } // Added later without breaking clients |
| 102 | public int? Priority { get; set; } // Added later without breaking clients |
| 103 | } |
| 104 | |
| 105 | public class ChatHub : Hub<IChatClient> |
| 106 | { |
| 107 | public async Task SendMessage(Se |