Клієнт SignalR .NET, який підключається до служби Azure SignalR в додатку Blazor .NET Core 3


11

Я намагаюся встановити зв’язок між моїм додатком ASP.NET Core 3.0 Blazor (на стороні сервера) та службою Azure SignalR. Я в кінцевому підсумку введу мій клієнт SignalR (послугу) в декілька компонентів Blazor, щоб вони в режимі реального часу оновили мій інтерфейс користувача / DOM.

Моя проблема полягає в тому, що я отримую таке повідомлення, коли я викликаю свій .StartAsync()метод на з'єднанні концентратора:

Код статусу відповіді не вказує на успіх: 404 (Не знайдено).

BootstrapSignalRClient.cs

Цей файл завантажує мою конфігурацію служби SignalR, включаючи URL, рядок з'єднання, ключ, ім'я методу та ім'я концентратора. Ці параметри фіксуються в статичному класі 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);
    }
}

У мене є досвід використання SignalR з .NET Core, куди ви додаєте його, щоб Startup.csфайл використовував .AddSignalR().AddAzureSignalR()і мабував концентратор у конфігурації програми, і це робиться таким чином, потрібно встановити певні параметри конфігурації (тобто рядок з'єднання).

З огляду на мою ситуацію, звідки береться HubConnectionBuilderрядок з'єднання або ключ для аутентифікації до служби SignalR?

Чи можливо повідомлення 404 є результатом відсутності рядка ключа / з'єднання?


1
.WithUrl(signalRConfig.Url + signalRConfig.HubName)Чи можете ви переконатися, що це призводить до отримання правильної URL-адреси? (За точкою розриву чи входом?)
Fildor

Мені Uri
здалося

що цікаво, це була «червона оселедець» і не мала нічого спільного з 404.
Jason Shave

Відповіді:


8

Гаразд, виходить, що документація не має тут ключової інформації. Якщо ви використовуєте клієнт .NET SignalR, який підключається до служби Azure SignalR, вам потрібно подати маркер JWT та подати його під час створення з'єднання концентратора.

Якщо вам потрібно здійснити автентифікацію від імені користувача, ви можете використовувати цей приклад.

В іншому випадку ви можете встановити кінцеву точку "/ узгодити" за допомогою веб-API, такого як функція Azure, щоб отримати для вас маркер JWT та клієнтську URL-адресу; саме це я і зробив для свого випадку використання. Інформацію про створення функції Azure для отримання маркера та URL-адреси JWT можна знайти тут.

Я створив клас для утримання цих двох значень як таких:

SignalRConnectionInfo.cs

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

Я також створив всередині себе метод SignalRServiceдля обробки взаємодії з кінцевою точкою "/ узгодження" веб-API в Azure, інстанціюванням з'єднання концентратора та використанням події + делегата для отримання повідомлень таким чином:

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 і сподіваюся, що це допоможе комусь іншому!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.