Máy khách SignalR .NET kết nối với dịch vụ Azure SignalR trong ứng dụng Blazor .NET Core 3


11

Tôi đang cố gắng tạo kết nối giữa ứng dụng ASP.NET Core 3.0 Blazor (phía máy chủ) và Dịch vụ Azure SignalR. Cuối cùng tôi sẽ đưa ứng dụng khách (dịch vụ) SignalR của mình vào một vài thành phần Blazor để họ sẽ cập nhật UI / DOM của tôi trong thời gian thực.

Vấn đề của tôi là tôi nhận được thông báo sau khi tôi gọi .StartAsync()phương thức của mình trên kết nối trung tâm:

Mã trạng thái phản hồi không biểu thị thành công: 404 (Không tìm thấy).

BootstrapSignalRClient.cs

Tệp này tải cấu hình của tôi cho Dịch vụ SignalR bao gồm URL, chuỗi kết nối, khóa, tên phương thức và tên trung tâm. Các cài đặt này được ghi lại trong lớp tĩnh SignalRServiceConfigurationvà được sử dụng sau.

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

Tín hiệuRClient.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);
    }
}

Tôi có kinh nghiệm sử dụng SignalR với .NET Core khi bạn thêm nó để Startup.cstệp sử dụng .AddSignalR().AddAzureSignalR()và ánh xạ một hub trong cấu hình ứng dụng và thực hiện theo cách này yêu cầu các tham số 'cấu hình' nhất định phải được thiết lập (ví dụ: chuỗi kết nối).

Với tình huống của tôi, HubConnectionBuilderlấy chuỗi kết nối hoặc khóa để xác thực Dịch vụ SignalR ở đâu?

Có thể thông báo 404 là kết quả của chuỗi khóa / kết nối bị thiếu?


1
.WithUrl(signalRConfig.Url + signalRConfig.HubName)Bạn có thể xác minh điều này dẫn đến Url chính xác không? (Bằng điểm dừng hoặc đăng nhập?)
Fildor

Tôi thấy thật hữu ích khi có Uri cơ sở Urivà xây dựng một cái hoàn chỉnh thông qua Uri (Uri, chuỗi)
Fildor

thú vị thay, đó là một "cá trích đỏ" và không liên quan gì đến 404.
Jason Shave

Câu trả lời:


8

Được rồi vì vậy hóa ra tài liệu đang thiếu một thông tin quan trọng ở đây. Nếu bạn đang sử dụng Máy khách .NET SignalR kết nối với Dịch vụ Azure SignalR, bạn cần yêu cầu mã thông báo JWT và trình bày nó khi tạo kết nối trung tâm.

Nếu bạn cần xác thực thay mặt người dùng, bạn có thể sử dụng ví dụ này.

Mặt khác, bạn có thể thiết lập điểm cuối "/ đàm phán" bằng API web như Hàm Azure để truy xuất mã thông báo JWT và URL ứng dụng khách cho bạn; đây là những gì tôi đã làm cho trường hợp sử dụng của tôi. Thông tin về cách tạo Hàm Azure để nhận mã thông báo JWT của bạn và URL có thể được tìm thấy ở đây.

Tôi đã tạo một lớp để giữ hai giá trị này như sau:

SignalRConnectionInfo.cs

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

Tôi cũng đã tạo một phương thức bên trong SignalRServiceđể xử lý sự tương tác với điểm cuối "/ đàm phán" của API web trong Azure, khởi tạo kết nối trung tâm và sử dụng một sự kiện + ủy nhiệm để nhận tin nhắn như sau:

Tín hiệuRClient.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();
}

Đơn functionsClientgiản chỉ là một kiểu được gõ mạnh được HttpClientcấu hình sẵn với URL cơ sở và FunctionsClientConstants.SignalRlà lớp tĩnh với đường dẫn "/ đàm phán" được gắn vào URL cơ sở.

Khi tôi đã cài đặt xong, tôi gọi await hubConnection.StartAsync();và "nó được kết nối"!

Sau tất cả, tôi thiết lập một ReceiveMessagesự kiện tĩnh và một đại biểu như sau (giống nhau SignalRClient.cs):

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

Cuối cùng, tôi đã thực hiện các ReceiveMessageđại biểu:

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

Tôi đã cung cấp các cập nhật tài liệu trở lại cho nhóm Dịch vụ Azure SignalR và chắc chắn hy vọng điều này sẽ giúp được người khác!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.