关于 aspnet-signalr
面向实现实时通信的开发者的 ASP.NET Core SignalR 速查技能,涵盖 Hub 配置、强类型客户端、流式传输、身份验证及常见故障排查。
主要功能
- 01映射 SignalR Hub
- 02定义强类型 Hub 客户端
- 03通过 IHubContext 发送消息
- 04在服务器与客户端间传输流
- 05为 Hub 和方法设置授权
适用场景
- 01搭建实时聊天 Hub
- 02在 Hub 方法外发送通知
- 03向已连接客户端传输服务器数据
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill aspnet-signalr安装后在 Claude Code 中输入/aspnet-signalr确认已加载。
详细介绍
ASP.NET Core SignalR - 快速参考
深入了解:使用
mcp__documentation__fetch_docs,并将技术名称设为:signalr,以获取完整文档。
Hub 设置
// Program.cs
builder.Services.AddSignalR();
app.MapHub<ChatHub>("/hubs/chat");
强类型 Hub
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
Task UserJoined(string user);
Task UserLeft(string user);
}
public class ChatHub : Hub<IChatClient>
{
public async Task SendMessage(string user, string message)
{
await Clients.All.ReceiveMessage(user, message);
}
public async Task JoinRoom(string room)
{
await Groups.AddToGroupAsync(Context.ConnectionId, room);
await Clients.Group(room).UserJoined(Context.User?.Identity?.Name ?? "Anonymous");
}
public async Task LeaveRoom(string room)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, room);
await Clients.Group(room).UserLeft(Context.User?.Identity?.Name ?? "Anonymous");
}
public override async Task OnConnectedAsync()
{
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
await base.OnDisconnectedAsync(exception);
}
}
从 Hub 外部发送
public class NotificationService
{
private readonly IHubContext<ChatHub, IChatClient> _hubContext;
public NotificationService(IHubContext<ChatHub, IChatClient> hubContext)
=> _hubContext = hubContext;
public async Task NotifyUser(string userId, string message)
{
await _hubContext.Clients.User(userId).ReceiveMessage("System", message);
}
public async Task NotifyGroup(string group, string message)
{
await _hubContext.Clients.Group(group).ReceiveMessage("System", message);
}
}
流式传输
public class StreamHub : Hub
{
// Server to client streaming
public async IAsyncEnumerable<int> Counter(int count, int delay,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
for (var i = 0; i < count; i++)
{
cancellationToken.ThrowIfCancellationRequested();
yield return i;
await Task.Delay(delay, cancellationToken);
}
}
// Client to server streaming
public async Task UploadStream(IAsyncEnumerable<string> stream)
{
await foreach (var item in stream)
{
// Process each item
}
}
}
身份验证
// Require auth on hub
[Authorize]
public class SecureHub : Hub<IChatClient>
{
[Authorize(Roles = "Admin")]
public async Task AdminAction() { }
}
// Access user info
public class ChatHub : Hub
{
public async Task Send(string message)
{
var userId = Context.UserIdentifier; // From ClaimTypes.NameIdentifier
var name = Context.User?.Identity?.Name;
}
}
反模式
| 反模式 | 不妥之处 | 正确做法 |
|---|---|---|
| 在 Hub 中存储状态 | Hub 是临时的 | 使用外部存储或组 |
| 不使用强类型 Hub | 没有编译时安全性 | 使用 Hub<TClient> |
| Hub 方法运行时间过长 | 阻塞连接 | 使用后台服务 |
| 不处理断开连接 | 造成资源泄漏 | 重写 OnDisconnectedAsync |
快速故障排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 连接被拒绝 | 未映射 Hub | 检查 app.MapHub<T>() |
| 身份验证不起作用 | 未发送令牌 | 使用 WebSocket 时通过查询字符串传递令牌 |
| 未收到消息 | 客户端方法名称错误 | 与接口方法名称完全一致 |
| 扩展性问题 | 没有 Backplane | 使用 Redis 或 Azure SignalR |
评论
支持 Markdown