Blazor .NET Core 3アプリケーションでAzure SignalRサービスに接続するSignalR .NETクライアント


11

ASP.NET Core 3.0 Blazor(サーバー側)アプリケーションとAzure SignalR Serviceを接続しようとしています。最終的に、SignalRクライアント(サービス)をいくつかのBlazorコンポーネントに注入して、UI / DOMをリアルタイムで更新できるようにします。

私の問題は.StartAsync()、ハブ接続でメソッドを呼び出すと、次のメッセージが表示されることです。

応答ステータスコードが成功を示さない:404(見つかりません)。

BootstrapSignalRClient.cs

このファイルは、URL、接続文字列、キー、メソッド名、ハブ名など、SignalRサービスの構成を読み込みます。これらの設定は静的クラスに取り込まれ、SignalRServiceConfiguration後で使用されます。

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

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

SignalRClient.cs

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

.NET CoreでSignalRを使用した経験があります。追加すると、アプリ構成でハブStartup.csを使用.AddSignalR().AddAzureSignalR()してマップするファイルを作成し、この方法で特定の「構成」パラメーターを確立する必要があります(つまり、接続文字列)。

私の状況ではHubConnectionBuilder、SignalRサービスへの認証のための接続文字列またはキーはどこで取得できますか?

404メッセージが欠落したキー/接続文字列の結果である可能性はありますか?


1
.WithUrl(signalRConfig.Url + signalRConfig.HubName)これにより正しいURLが生成されることを確認できますか?(ブレークポイントまたはログによるか?)
Fildor '10 / 10/19

ベースのUriをasにして、Uri(Uri、string)Uriを介して完全なものを構築すると便利です
Fildor

興味深いことにそれは赤いニシン」だったと404とは何の関係もなかった
ジェイソン・シェービング

回答:


8

わかりましたので、ドキュメントにはここで重要な情報が不足しています。Azure SignalRサービスに接続する.NET SignalRクライアントを使用している場合は、JWTトークンをリクエストし、ハブ接続を作成するときにそれを提示する必要があります。

ユーザーに代わって認証する必要がある場合は、この例を使用できます

それ以外の場合は、Azure FunctionなどのWeb APIを使用して「/ negotiate」エンドポイントを設定し、JWTトークンとクライアントURLを取得できます。これは私が私のユースケースのためにやったことです。JWTトークンとURLを取得するためのAzure関数の作成に関する情報は、こちらにあります。

この2つの値を保持するクラスを作成しました。

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単に強く型付けされているHttpClientベースURLで予め設定され、FunctionsClientConstants.SignalR「/交渉する」ベースURLに付加されるパスと静的クラスです。

これをすべて設定したら、を呼び出し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 Serviceチームに提供しましたが、これが他の人の役に立つことを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.