.NetCore项目SignalR获取客户端信息的测试
.Net7 新增了 SignalR 可以获取客户端数据的方法,即原方法 InvokeAsync 支持返回值,这里结合官网做了测试,作为记录
1. SignalR注入
路
2. 环境搭建
继续略
3. 升级本地SignalRJS
结合这两个地址
ASP.NET Core SignalR JavaScript 客户端
注意js版本号7.0+,下到本地也行,从vs2022添加客户端也行,如果本地低在调用js方法后会显示版本不支持;
4. 服务端
/// <summary>
/// 得到客户端结果
/// </summary>
/// <param name="evname"></param>
/// <param name="msg"></param>
/// <param name="id"></param>
/// <returns></returns>
public static async Task<dynamic> GetHubMessage(string evname, string msg, string id = "")
{
//尝试拿一个hubid
if (string.IsNullOrEmpty(id)) { id = GetHubID(); }
if (string.IsNullOrEmpty(id)) { return default; }
var Hub = PageContext.GetServerByApp<IHubContext<SignalRHub>>();
var msr = await Hub.Clients.Client(id).InvokeAsync<dynamic>(evname, msg, new CancellationToken());
return msr ?? default;
}
/// <summary>
/// 尝试得到本次的hubid
/// </summary>
/// <returns></returns>
public static string GetHubID()
{
var hubid = string.Empty;
var head = PageContext.Current!.Request.Headers;
if (head.ContainsKey("hubid"))
{
hubid = head["hubid"];
}
else if (PageContext.Current!.Request.Form.ContainsKey("hubid"))
{
hubid = PageContext.Current!.Request.Form["hubid"];
}
return hubid;
}
以上代码 核心方法就是 InvokeAsync ,其他都来自服务就可以了,注意接收值,前台的返回我测试了 数组 对象,后台的接到到的类型是 System.Text.Json , 而不是 Newtonsoft.Json,尽量返回字符串比较稳定;用的时候直接调用即可 GetHubMessage("getMessage","Grid1");
我这里触发的前端方法是 getMessage 如果前端没有注册 getMessage ,则会提示
Client didn't provide a result.(客户端没有返回结果)
5. 客户端
const connection = new signalR
.HubConnectionBuilder()
.withUrl("/HomeHub")
.build();
window.hub.connection = connection;
...
window.hub.connection.on(`getMessage`,async (msg)=>{
return JSON.stringify(F.ui[msg].fields);
});
这里注意了,我的HomeHub连接是在顶层框架页面,即只有一个实例,如果同一个实例注册多个方法即getMessage并返回结果,会报错,Client provided multiple results(客户端提供了多个结果);
6. 应用
这样就拿到数据了,那在什么情况下会用到呢,场景要有几个特点,数据回发提交的时候有的参数没带着,或者带不了;或者这是客户端还没有数据,等会才有;或者需要等待客户继续操作后才能拿到结果;
一个典型的场景就是确认Confirm,之前我已经将F.confirm 改为异步了,用Promise包一下就行;之前也改造过等待客户响应的方法,使用客户端响应后二次提交从缓存拿到任务再改变状态,绕了一大圈,存在超时和中断问题;升级之后,后台执行到需要客户选择的代码,可以直接由服务端发起,然后等着前台返回就行了,省去了不少代码;
其他应用场景还有待探索。