非常熟悉ASP.NET/ASP.NET核心环境(通常使用DevExpress在WinForms中工作),并且在try 理解和实现调用客户端方法的SignalR服务器时遇到一些问题.根据我对这Using Hubs in SignalR article的"客户端结果"部分的理解,我应该能够从服务器调用客户端上的一些方法.这在大多数情况下都有效;但是,当我try 在客户端调用一个接受参数并返回结果的方法时,我得到了一个错误:System.Exception: 'Client didn't provide a result.'
,我似乎找不到关于它的更多信息.
在本例中,我的服务器是一个面向.NET 7(.csproj中为<TargetFramework>net7.0</TargetFramework>
)的基本ASP.NET核心应用程序,而我的客户端是一个面向.NET 7 Windows(net7.0-windows
)并使用Microsoft.AspNetCore.SignalR.Client
NuGet包( compose 本文时为7.0.7)的WinForms应用程序.
我的目标是最终拥有一个WinForms"SignalR服务器",它可以与各种客户端通信,但使用一个连接的客户端作为"主客户端".我还没有构建任何代码,所以我只是将我的第一个连接的客户端用作"主客户端".
以下是我的服务器端代码(使用强类型集线器):
public interface IStrongServer
{
Task<Boolean> TestBoolean();
Task<Boolean> TestBooleanWithParameters(string toSend);
}
public class StrongServerHub : Hub<IStrongServer>
{
private readonly StrongServer _StrongServer;
public StrongServerHub(StrongServer nStrongServer)
{
_StrongServer = nStrongServer;
}
public override async Task OnConnectedAsync()
{
_StrongServer.AssignPrimaryConnection(this.Context.ConnectionId);
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
_StrongServer.DisconnectPrimaryConnection(this.Context.ConnectionId);
await base.OnDisconnectedAsync(exception);
}
}
public class StrongServer : IStrongServer
{
private string PrimaryConnectionId = "";
private bool PrimaryConnected = false;
private IHubContext<StrongServerHub, IStrongServer> Hub
{
get;
set;
}
public StrongServer(IHubContext<StrongServerHub, IStrongServer> hub)
{
Hub = hub;
}
public void AssignPrimaryConnection(string connectionId)
{
if (String.IsNullOrEmpty(PrimaryConnectionId))
{
PrimaryConnectionId = connectionId;
PrimaryConnected = true;
}
}
public void DisconnectPrimaryConnection(string connectionId)
{
if (!String.IsNullOrEmpty(PrimaryConnectionId) && String.Equals(PrimaryConnectionId, connectionId))
{
PrimaryConnectionId = "";
PrimaryConnected = false;
}
}
public async Task<bool> TestBoolean()
{
return await Hub.Clients.Client(PrimaryConnectionId).TestBoolean();
}
public async Task<bool> TestBooleanWithParameters(string ToSend)
{
return await Hub.Clients.Client(PrimaryConnectionId).TestBooleanWithParameters(ToSend);
}
}
public class SignalRHost
{
public StrongServer Server { get; set; }
public void Run()
{
var builder = WebApplication.CreateBuilder();
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
builder.Services.AddSingleton<StrongServer>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.MapHub<StrongServerHub>("/strong");
Server = app.Services.GetService<StrongServer>();
app.RunAsync();
}
}
// Then in Program.cs, I'd do:
SignalRHost host = new SignalRHost();
host.Run();
bool returnedBoolean = await host.Server.TestBoolean();
bool returnedBooleanWithParameters = await host.Server.TestBooleanWithParameters("Hello World!");
下面是我的客户端代码:
public interface ITestClient
{
bool TestBoolean();
bool TestBooleanWithParameters(string test);
}
using System.Diagnostics;
public class SignalRClient : ITestClient
{
HubConnection TestConnection = null;
public async void Init()
{
TestConnection = new HubConnectionBuilder().WithUrl("http://localhost:5035/strong").Build(); // The port 5035 is what my machine used.
TestConnection.On(nameof(TestBoolean), TestBoolean);
TestConnection.On<string>(nameof(TestBooleanWithParameters), (p1) => TestBooleanWithParameters(p1));
await TestConnection.StartAsync();
}
public bool TestBoolean()
{
return true;
}
public bool TestBooleanWithParameters(string test)
{
Debug.WriteLine($"TestBooleanReturn: {test}"); ;
return true;
}
}
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
SignalRClient client = new SignalRClient();
client.Init();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
同样,ASP.NET和ASP.NET Core之间的差异让我非常困惑,所以我的第一个 idea 是它可能是一个
TLDR:如果客户端方法有参数,来自客户端的预期结果是不可能的吗?我是不是漏掉了什么明显的东西?