SignalR客户端ReceiveClientHub回调未触发及参数为空问题求助
SignalR客户端回调异常及参数为空问题
问题现象
- 初始状态:FITBSignalRService运行在Fragment中,客户端能正常连接SignalR服务,调用
hubConnection.send("BroadcastClient", "adad", "adad")正常,但hubConnection.on("ReceiveClientHub")的回调始终不触发。 - 更新代码后:回调可以触发,但接收的
userId和peerId参数均为null。
初始代码
Java客户端代码
package com.example.fireinthebooth; import android.app.Activity; import android.app.Service; import android.content.Intent; import android.os.AsyncTask; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import androidx.annotation.Nullable; import com.microsoft.signalr.HubConnection; import com.microsoft.signalr.HubConnectionBuilder; import java.util.ArrayList; public class FITBSignalRService { private HubConnection mHubConnection; private Handler mHandler; // to display Toast message public class PullRequest { public String Url; public Integer PullRequestId; public String Avatar; public String Login; public String Title; } ArrayList<PullRequest> pullRequests = new ArrayList<PullRequest>(); public FITBSignalRService(Activity context, String url) throws InterruptedException { HubConnection hubConnection = HubConnectionBuilder .create("https://xxxxx/fitbHub") .build(); hubConnection.on("ReceiveClientHub", (ReceivePeerData)-> { context.runOnUiThread(new Runnable() { @Override public void run() { } }); }, ReceivePeerData.class); hubConnection.start() .doOnError(throwable -> { //start fail , try again //note: the start function need try chach when we use this function }) .doOnComplete(() -> { //start complated int i = 0; hubConnection.send("BroadcastClient", "adad", "adad"); }) .blockingAwait(); } static class HubConnectionTask extends AsyncTask<HubConnection, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(HubConnection... hubConnections) { HubConnection hubConnection = hubConnections[0]; try{ hubConnection.start(); }catch(Exception e){ int g = 0; } return null; } } class ReceivePeerData{ Object userId; Object peerId; } }
C#服务端代码
using Microsoft.AspNetCore.SignalR; namespace FireInTheBoothAPI.SignalR { public class FITBHub :Hub { public async Task BroadcastClient(string userId, string peerId) { await Clients.All.SendAsync("ReceiveClientHub", userId, peerId); } } }
Program.cs代码
using FireInTheBoothAPI.Endpoints; using FireInTheBoothAPI.SignalR; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddSignalR(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.FITB(); app.MapHub<FITBHub>("/fitbHub"); app.Run();
更新后的代码
Java客户端ReceivePeerData类修改为:
class ReceivePeerData{ public String userId; public String peerId; }
C#服务端修改为:
public class FITBHub :Hub { public async Task BroadcastClient(string userId, string peerId) { await Clients.All.SendAsync("ReceiveClientHub", new ReceivePeerData() { userId = userId, peerId = peerId }); } class ReceivePeerData { public string userId; public string peerId; } }
问题分析与修复方案
1. 初始回调不触发的原因
服务端调用SendAsync时直接传递了两个独立的字符串参数,但客户端注册回调时期望接收一个ReceivePeerData对象,参数类型不匹配导致SignalR无法找到对应的回调方法,所以回调不触发。
2. 更新后参数为空的原因及修复
虽然两端改成了对象传递,但仍有几个细节需要修正:
服务端嵌套类访问权限:服务端的
ReceivePeerData是私有嵌套类,JSON序列化时无法正常识别属性,需改为public,同时建议用属性而非字段提升序列化兼容性:public class ReceivePeerData { public string userId { get; set; } public string peerId { get; set; } }客户端连接对象生命周期:原代码中
hubConnection是构造函数内的局部变量,可能被GC回收导致连接异常,需改为使用类成员变量mHubConnection:// 替换构造函数内的局部连接对象 mHubConnection = HubConnectionBuilder .create("https://xxxxx/fitbHub") .build(); mHubConnection.on("ReceiveClientHub", (ReceivePeerData data)-> { context.runOnUiThread(() -> { // 这里可以正常获取data.userId和data.peerId }); }, ReceivePeerData.class); mHubConnection.start() .doOnError(throwable -> { // 处理启动错误逻辑 }) .doOnComplete(() -> { mHubConnection.send("BroadcastClient", "adad", "adad"); }) .blockingAwait();序列化一致性:确保两端JSON序列化规则一致,比如属性名称大小写匹配(当前
userId小驼峰两端一致,没问题),客户端ReceivePeerData的属性必须是public,且有无参构造函数(Java默认提供,无需额外定义)。
按上述方案修改后,客户端就能正常触发回调并接收正确的参数值。
内容的提问来源于stack exchange,提问作者redoc01
相关产品推荐
相关产品推荐

