跳到主要内容
版本:3.0.0

SignalR

3.0.0 页面说明

  • 3.0.0 说明:当前页已恢复详细示例,避免正文信息丢失。
  • 当前包名统一为 Aegis.Net.SignalR;如遇到历史命名差异,请以本页和组件页为准。
  • 组件入口: Aegis.Net.SignalR

SignalR 是微软开发的一个 实时通信库,用于在 .NET 应用中实现服务器与客户端(如网页、桌面 App)之间的双向、实时数据传输。 它的核心价值在于简化实时通信开发,无需手动处理底层的 WebSocket 协议、轮询等复杂逻辑,让开发者专注于业务功能。

核心特点:

  • 自动适配传输方式:优先使用高效的 WebSocket 协议,若环境不支持(如旧浏览器、网络限制),会自动降级为 Server-Sent Events、长轮询等方式。
  • 双向通信:服务器可主动向客户端推送数据(如实时通知、聊天消息),客户端也能实时向服务器发送请求,打破传统 HTTP “请求 - 响应” 的单向模式。
  • 跨平台兼容:支持多种客户端,包括 JavaScript(网页)、.NET(桌面 / 移动)、Java(Android)等,可用于构建全平台实时应用

如何引入

SignalR功能包含在Aegis.Net.SignalR的Nuget包中,在引入之后请确认Component.deps.json配置文件中的ServicesMiddlewares节点中含有SignalR

image.png|1000

appsettings.json或者加载的配置文件中包含SignalR节点的配置,具体参考如下

{
"SignalR": {
//支持分布式的连接字符串
"DistributedConnection": "",
//开放的传输方式(WebSockets、ServerSentEvents、LongPolling),多个用逗号隔开,为空则全部开放
"TransportType": "WebSockets,ServerSentEvents,LongPolling"
}
}

说明

只要继承了Hub类,就会自动注入到当前应用中。

使用方法

SignalR的服务类

在Api项目下的Hubs文件夹中新建xxHub类,这个就是SignalR Hub的服务中心

image.png|400

public class xxHub : Hub
{
/// <summary>
/// 发送消息
/// </summary>
/// <param name="request">消息</param>
public async Task SendMessage(MessageRequest request)
{
var message = $"Hello {request.Message}";

await Clients.All.SendAsync("ReceiveMessage", new MessageResponse
{
Message = message
});
}
}

以上示例代码就是一个接收和发送消息的例子,方法说明:

  • SendMessage就是开放给客户端调用的方法,建议所有的方法都使用Request类来接收参数
  • Clients.All.SendAsync("ReceiveMessage", 参数)这个就是让所有连接的客户端接收名为ReceiveMessage的消息,参数也建议用类来包装
    • 发送方式有以下三种:
      • Clients.All:向所有连接的客户端发送消息
      • Clients.Caller:向调用了中心方法的客户端发送消息
      • Clients.Others:向所有连接的客户端发送消息(调用了方法的客户端除外)
    • 强类型Hub:为了防止SendAsync("ReceiveMessage")时,方法名出现拼写错误或缺失,推荐使用强类型Hub
        public interface IChatClient
      {
      Task ReceiveMessage(MessageResponse response);
      }

      public class xxHub : Hub<IChatClient>
      {
      /// <summary>
      /// 发送消息
      /// </summary>
      /// <param name="request">消息</param>
      public async Task SendMessage(MessageRequest request)
      {
      var message = $"Hello {request.Message}";

      //直接调用方法 ReceiveMessage
      await Clients.All.ReceiveMessage(new MessageResponse
      {
      Message = message
      });
      }
      }
  • 向后兼容性:用类来包装入参和出参,是为了确保向后兼容性,具体可参考 https://learn.microsoft.com/zh-cn/aspnet/core/signalr/api-design?view=aspnetcore-6.0

认证鉴权重写

public class xxHub : Hub
{
/// <summary>
/// 建立连接
/// </summary>
/// <returns></returns>
public override Task OnConnectedAsync()
{
Console.WriteLine($"{Context.ConnectionId}-建立连接");
return base.OnConnectedAsync();
}

/// <summary>
/// 断开连接
/// </summary>
/// <param name="exception">错误原因</param>
/// <returns></returns>
public override Task OnDisconnectedAsync(Exception? exception)
{
Console.WriteLine($"{Context.ConnectionId}-断开连接");
return base.OnDisconnectedAsync(exception);
}
}

以上示例代码是Hub类连接时和断开时会执行的方法,是虚方法,可按需决定是否需要重写

在Hub外部使用

在实际的业务使用中,可能也会存在在Controller中需要发送消息的情况,那么可参考下面的示例。具体可参考: https://learn.microsoft.com/zh-cn/aspnet/core/signalr/hubcontext?view=aspnetcore-6.0

public class HomeController : Controller
{
//未使用强类型
private readonly IHubContext<xxHub> _hubContext;
//使用强类型
public readonly IHubContext<xxHub, IChatClient> _chatHubContext

public HomeController(IHubContext<xxHub> hubContext, IHubContext<xxHub, IChatClient> chatHubContext)
{
_hubContext = hubContext;
_chatHubContext = chatHubContext;
}

//未使用强类型
public async Task<IActionResult> SendMessage1()
{
await _hubContext.Clients.All.SendAsync("ReceiveMessage", new MessageResponse
{
Message = "Hello World"
});

return SuccessResult("OK");
}

//使用强类型
public async Task<IActionResult> SendMessage2()
{
await _hubContext.Clients.All.ReceiveMessage(new MessageResponse
{
Message = "Hello World"
});

return SuccessResult("OK");
}
}