ไคลเอ็นต์ SignalR .NET เชื่อมต่อกับบริการ Azure SignalR ในแอปพลิเคชัน Blazor .NET Core 3


11

ฉันกำลังพยายามเชื่อมต่อระหว่างแอปพลิเคชัน ASP.NET Core 3.0 Blazor (ฝั่งเซิร์ฟเวอร์) กับ Azure SignalR Service ฉันจะลงเอยด้วยการฉีดไคลเอนต์ SignalR (บริการ) ของฉันไปยังองค์ประกอบ Blazor บางอย่างเพื่อให้พวกเขาอัปเดต UI / 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 เป็นUriและสร้างหนึ่งที่สมบูรณ์ผ่านUri (Uri, สตริง)
5146

ที่น่าสนใจก็คือ 'ปลาเฮอริ่งแดง' และไม่มีส่วนเกี่ยวข้องกับ 404
Jason Shave

คำตอบ:


8

ตกลงดังนั้นปรากฎว่าเอกสารกำลังขาดข้อมูลสำคัญที่นี่ หากคุณใช้. NET SignalR Client เชื่อมต่อกับบริการ Azure SignalR คุณจะต้องขอโทเค็น JWT และนำเสนอเมื่อสร้างการเชื่อมต่อฮับ

หากคุณต้องการตรวจสอบสิทธิ์ในนามของผู้ใช้คุณสามารถใช้ตัวอย่างนี้

มิฉะนั้นคุณสามารถตั้งค่าปลายทาง "/ เจรจาต่อรอง" โดยใช้เว็บ API เช่นฟังก์ชัน Azure เพื่อดึงโทเค็น JWT และ URL ไคลเอ็นต์กลับมาให้คุณ นี่คือสิ่งที่ฉันทำลงไปสำหรับกรณีการใช้งานของฉัน ข้อมูลเกี่ยวกับการสร้างฟังก์ชัน 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เพื่อจัดการกับการโต้ตอบกับจุดสิ้นสุด "/ เจรจา" ของเว็บ 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();
}

The 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 แล้วและหวังว่านี่จะช่วยคนอื่นได้!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.