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

时间:2019-10-05 21:00:31

标签: c# signalr signalr.client asp.net-core-signalr azure-signalr

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

我的问题是,当我在集线器连接上调用 {"id":"xxx", "amount":300} Instead of {"id":"xxx", "amount":300.0} 方法时,我收到以下消息:

  

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

BootstrapSignalRClient.cs

此文件加载我对SignalR服务的配置,包括URL,连接字符串,键,方法名称和集线器名称。这些设置捕获在静态类.StartAsync()中,以后再使用。

SignalRServiceConfiguration

SignalRServiceConfiguration.cs

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;
    }
}

SignalRClient.cs

public class SignalRServiceConfiguration
{
    public string ConnectionString { get; set; }
    public string Url { get; set; }
    public string MethodName { get; set; }
    public string Key { get; set; }
    public string HubName { get; set; }
}

我在将SignalR与.NET Core结合使用方面经验丰富,您可以在其中添加它,以便使用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); } } 来复制Startup.cs文件并在应用程序配置中映射一个集线器,并且这样做需要某些“配置”参数建立(即连接字符串)。

鉴于我的情况,.AddSignalR().AddAzureSignalR()在哪里获得连接字符串或密钥以对SignalR服务进行身份验证?

404消息是否可能是缺少键/连接字符串的结果?

2 个答案:

答案 0 :(得分:5)

好的,事实证明,这里的文档缺少关键信息。如果您使用的是连接到Azure SignalR服务的.NET SignalR客户端,则需要请求JWT令牌并在创建集线器连接时出示该令牌。

如果您需要代表用户进行身份验证,则可以使用this example.

否则,您可以使用Web API(例如Azure函数)设置“ /协商”终结点,以为您检索JWT令牌和客户端URL。这就是我最终为用例所做的事情。 here.

可找到有关创建Azure函数以获取JWT令牌和URL的信息。

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

SignalRConnectionInfo.cs

public class SignalRConnectionInfo
{
    [JsonProperty(PropertyName = "url")]
    public string Url { get; set; }
    [JsonProperty(PropertyName = "accessToken")]
    public string AccessToken { get; set; }
}

我还在SignalRService内创建了一个方法来处理与Azure中Web API的“ / negotiate”终结点的交互,集线器连接的实例化以及使用事件+委托来接收消息的方式如下:

SignalRClient.cs

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();
}

functionsClient只是预先配置了基本URL的强类型HttpClient,而FunctionsClientConstants.SignalR是带有附加到基本地址的“ / negotiate”路径的静态类。网址。

设置完所有步骤后,我叫await hubConnection.StartAsync();,它就“连接”了!

所有这些之后,我如下设置了一个静态ReceiveMessage事件和一个委托(在同一SignalRClient.cs中):

public delegate void ReceiveMessage(string message);
public static event ReceiveMessage ReceiveMessageEvent;

最后,我实现了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)
}

我已经向Azure SignalR服务团队提供了文档更新,希望可以对其他人有所帮助!

答案 1 :(得分:-1)

更新:该示例带有管理SDK(is deprecated)的无服务器示例sample。管理SDK使用协商服务器。