C# 连接到Blazor.NET Core 3应用程序中Azure Signal服务的Signal.NET客户端

C# 连接到Blazor.NET Core 3应用程序中Azure Signal服务的Signal.NET客户端,c#,signalr,signalr.client,asp.net-core-signalr,azure-signalr,C#,Signalr,Signalr.client,Asp.net Core Signalr,Azure Signalr,我正在尝试在我的ASP.NET Core 3.0 Blazor(服务器端)应用程序和Azure Signal服务之间建立连接。最后,我将把我的SignalR客户端(服务)注入到一些Blazor组件中,以便它们能够实时更新我的UI/DOM 我的问题是,在调用集线器连接上的.StartAsync()方法时,我收到以下消息: 响应状态代码不表示成功:404(未找到) BootstrapSignalRClient.cs 此文件加载信号器服务的配置,包括URL、连接字符串、键、方法名称和集线器名称。这些设

我正在尝试在我的ASP.NET Core 3.0 Blazor(服务器端)应用程序和Azure Signal服务之间建立连接。最后,我将把我的SignalR客户端(服务)注入到一些Blazor组件中,以便它们能够实时更新我的UI/DOM

我的问题是,在调用集线器连接上的
.StartAsync()
方法时,我收到以下消息:

响应状态代码不表示成功:404(未找到)

BootstrapSignalRClient.cs 此文件加载信号器服务的配置,包括URL、连接字符串、键、方法名称和集线器名称。这些设置在静态类
SignalServiceConfiguration
中捕获,稍后使用

public static class BootstrapSignalRClient
{
    public static IServiceCollection AddSignalRServiceClient(this IServiceCollection services, IConfiguration configuration)
    {
        SignalRServiceConfiguration signalRServiceConfiguration = new SignalRServiceConfiguration();
        configuration.Bind(nameof(SignalRServiceConfiguration), signalRServiceConfiguration);

        services.AddSingleton(signalRServiceConfiguration);
        services.AddSingleton<ISignalRClient, SignalRClient>();

        return services;
    }
}
SignalClient.cs
公共类信号客户端:ISignalClient
{
公共委托无效接收消息(字符串消息);
公共事件接收消息接收消息事件;
专用HUB连接HUB连接;
公共信号客户端(信号服务配置信号配置)
{
hubConnection=新的HubConnectionBuilder()
.WithUrl(signalConfig.Url+signalConfig.HubName)
.Build();
}
公共异步任务侦听(字符串id)
{
//为特定id注册侦听器
hubConnection.On(id,(消息)=>
{
if(ReceiveMessageEvent!=null)
{
ReceiveMessageEvent.Invoke(消息);
}
});
尝试
{
//启动信号机服务连接

等待hubConnection.StartAsync();//好的,因此文档中缺少此处的关键信息。如果您正在使用连接到Azure Signal服务的.NET Signal客户端,则需要请求JWT令牌,并在创建集线器连接时提供该令牌

如果需要代表用户进行身份验证,可以使用

否则,您可以使用web API(如Azure函数)设置“/协商”终结点,以便为您检索JWT令牌和客户端URL;这就是我为我的用例所做的。可以找到有关创建Azure函数以获取JWT令牌和URL的信息

我创建了一个类来保存这两个值:

SignalRConnectionInfo.cs 我还在我的
SignalRService
中创建了一个方法,用于处理与Azure中web API的“/协商”端点的交互、集线器连接的实例化以及使用事件+委托接收消息,如下所示:

SignalClient.cs 最后,我实现了
ReceiveMessage
委托:

await signalRClient.InitializeAsync(); //<---called from another method

private async Task StartReceiving()
{
    SignalRStatus = await signalRClient.ReceiveReservationResponse(Response.ReservationId);
    logger.LogInformation($"SignalR Status is: {SignalRStatus}");

    // Register event handler for static delegate
    SignalRClient.ReceiveMessageEvent += signalRClient_receiveMessageEvent;
}

private async void signalRClient_receiveMessageEvent(string response)
{
    logger.LogInformation($"Received SignalR mesage: {response}");
    signalRReservationResponse = JsonConvert.DeserializeObject<SignalRReservationResponse>(response);
    await InvokeAsync(StateHasChanged); //<---used by Blazor (server-side)
}


等待SignalClient.InitializeAsync();//更新:管理SDK()的无服务器示例的示例。管理SDK使用协商服务器。

。使用Url(SignalConfig.Url+SignalConfig.HubName)
可以验证这是否生成了正确的Url吗?(通过断点或日志记录?)我发现将基本Uri设置为
Uri
很有用,并通过有趣的方式构建完整的Uri。这是一条“红鲱鱼”,与404无关。我知道这应该是一条注释,而不是答案,但我无法将其添加为注释-缺少必要的要点:(
public class SignalRClient : ISignalRClient
{
    public delegate void ReceiveMessage(string message);
    public event ReceiveMessage ReceiveMessageEvent;

    private HubConnection hubConnection;

    public SignalRClient(SignalRServiceConfiguration signalRConfig)
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(signalRConfig.Url + signalRConfig.HubName)
            .Build();            
    }

    public async Task<string> StartListening(string id)
    {
        // Register listener for a specific id
        hubConnection.On<string>(id, (message) => 
        {
            if (ReceiveMessageEvent != null)
            {
                ReceiveMessageEvent.Invoke(message);
            }
        });

        try
        {
            // Start the SignalR Service connection
            await hubConnection.StartAsync(); //<---I get an exception here
            return hubConnection.State.ToString();
        }
        catch (Exception ex)
        {
            return ex.Message;
        }            
    }

    private void ReceiveMessage(string message)
    {
        response = JsonConvert.DeserializeObject<dynamic>(message);
    }
}
public class SignalRConnectionInfo
{
    [JsonProperty(PropertyName = "url")]
    public string Url { get; set; }
    [JsonProperty(PropertyName = "accessToken")]
    public string AccessToken { get; set; }
}
public async Task InitializeAsync()
{
    SignalRConnectionInfo signalRConnectionInfo;
    signalRConnectionInfo = await functionsClient.GetDataAsync<SignalRConnectionInfo>(FunctionsClientConstants.SignalR);

    hubConnection = new HubConnectionBuilder()
        .WithUrl(signalRConnectionInfo.Url, options =>
        {
           options.AccessTokenProvider = () => Task.FromResult(signalRConnectionInfo.AccessToken);
        })
        .Build();
}
public delegate void ReceiveMessage(string message);
public static event ReceiveMessage ReceiveMessageEvent;
await signalRClient.InitializeAsync(); //<---called from another method

private async Task StartReceiving()
{
    SignalRStatus = await signalRClient.ReceiveReservationResponse(Response.ReservationId);
    logger.LogInformation($"SignalR Status is: {SignalRStatus}");

    // Register event handler for static delegate
    SignalRClient.ReceiveMessageEvent += signalRClient_receiveMessageEvent;
}

private async void signalRClient_receiveMessageEvent(string response)
{
    logger.LogInformation($"Received SignalR mesage: {response}");
    signalRReservationResponse = JsonConvert.DeserializeObject<SignalRReservationResponse>(response);
    await InvokeAsync(StateHasChanged); //<---used by Blazor (server-side)
}