本文将介绍如何在 .NET Core 环境下,借助 SignalR 在小程序内使用 WebSocket。关于 WebSocket 和 SignalR 的基础理论知识不在这里展开,已经有足够的参考资料,例如参考 SignalR 的官方教程:ASP.NET Core SignalR 概述 | Microsoft Learn
我们先看一下完成本教程内容后,在小程序内实现的 WebSocket 效果:
私有及群发消息
小程序模板消息
上图中包含了只有发送者本人可以收到的消息,以及群发的消息,还有一条发送者本人收到的模板消息。
所有代码都已开源,可以在 GitHub - JeffreySu/WeiXinMPSDK: 微信全平台 SDK Senparc.Weixin for C#,支持 .NET Framework 及 .NET Core、.NET 6.0、.NET 7.0。已支持微信公众号、小程序、小游戏、微信支付、企业微信/企业号、开放平台、JSSDK、微信周边等全平台。 WeChat SDK for C#. 中找到,其中服务器端代码位于 /Samples/Senparc.Weixin.MP.Sample.vs2017/Senparc.Weixin.MP.Sample.vs2017.sln 解决方案中,小程序客户端代码位于 /src/Senparc.Weixin.WxOpen/src/Senparc.Weixin.WxOpen.AppDemo 中。
下面让我们开始吧!
服务器端
首先,我们需要通过 nuget 安装 Separc.WebSocket 包:NuGet Gallery | Senparc.WebSocket 0.17.12.2。Senparc.WebSocket 包提供了可供小程序使用的 WebScoket 的基础功能封装(当然,它也可以被很好地使用在小程序以外的场景,只不过在其他场景中我们通常有更多的选择,以及更多的复杂的业务需求)。
注意:Senparc.WebSocket 提供了针对 .NET Framework 4.5 和 .NET Standard 2.0(支持 .NET Core)的两个版本。其中,前者使用了相对比较底层的 WebSocket 构建方式,而后者我们直接使用了 SignalR,因为 .NET Core 下的 SignalR 官方摆脱了对 jQuery 的依赖,而 jQuery 在微信小程序中是不被支持的,这也是为什么我们没有在 .NET Framework 4.5 中没有使用 SignalR 这个优秀组件的原因。
安装完毕 Senparc.WebSocket 之后,我们还需要在 startup.cs 中对其进行启用,如在 ConfigureServices() 方法中添加代码:
services.AddSenparcWebSocket<CustomNetCoreWebSocketMessageHandler>();//Senparc.WebSocket 注册(按需)
注意:上述过程会附带执行 services.AddSignalR(); 指令,因此如果你在系统的其他地方也需要使用 SIgnalR,那么可以忽略对其注册过程。
关于上述方法中的泛型 CustomNetCoreWebSocketMessageHandler,其逻辑类似于公众号的 CustomMessageHandler,用于对消息进行同一的处理。让我们来看一下 CustomNetCoreWebSocketMessageHandler.cs的样子:
1 using System;
2 using System.Linq;
3 using System.Threading.Tasks;
4 using Senparc.WebSocket;
5 using Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage;
6 using Senparc.Weixin.WxOpen.Containers;
7
8 namespace Senparc.Weixin.MP.Sample.CommonService.MessageHandlers.WebSocket
9 {
10 /// <summary>
11 /// .NET Core 自定义 WebSocket 处理类
12 /// </summary>
13 public class CustomNetCoreWebSocketMessageHandler : WebSocketMessageHandler
14 {
15 public override Task OnConnecting(WebSocketHelper webSocketHandler)
16 {
17 //TODO:处理连接时的逻辑
18 return base.OnConnecting(webSocketHandler);
19 }
20
21 public override Task OnDisConnected(WebSocketHelper webSocketHandler)
22 {
23 //TODO:处理断开连接时的逻辑
24 return base.OnDisConnected(webSocketHandler);
25 }
26
27
28 public override async Task OnMessageReceiced(WebSocketHelper webSocketHandler, ReceivedMessage receivedMessage, string originalData)
29 {
30 if (receivedMessage == null || string.IsNullOrEmpty(receivedMessage.Message))
31 {
32 return;
33 }
34
35 var message = receivedMessage.Message;
36
37 await webSocketHandler.SendMessage("originalData:" + originalData, webSocketHandler.WebSocket.Clients.Caller);
38 await webSocketHandler.SendMessage("您发送了文字:" + message, webSocketHandler.WebSocket.Clients.Caller);
39 await webSocketHandler.SendMessage("正在处理中(反转文字)...", webSocketHandler.WebSocket.Clients.Caller);
40
41 await Task.Delay(1000);
42
43 //处理文字
44