在 Blazor .NET Core 3 应用程序中连接到 Azure SignalR 服务的 SignalR .NET 客户端
SignalR .NET Client connecting to Azure SignalR Service in a Blazor .NET Core 3 application
我正在尝试在我的 ASP.NET Core 3.0 Blazor(服务器端)应用程序和 Azure SignalR 服务之间建立连接。我最终会将我的 SignalR 客户端(服务)注入到一些 Blazor 组件中,以便它们实时更新我的 UI/DOM。
我的问题是,当我在集线器连接上调用 .StartAsync()
方法时收到以下消息:
Response status code does not indicate success: 404 (Not Found).
BootstrapSignalRClient.cs
此文件加载我的 SignalR 服务配置,包括 URL、连接字符串、密钥、方法名称和集线器名称。这些设置在静态 class 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()
并在应用程序配置中映射一个集线器,这样做需要某些 'configuration' 待建立的参数(即连接字符串)。
鉴于我的情况,HubConnectionBuilder
从哪里获取连接字符串或密钥以对 SignalR 服务进行身份验证?
404 消息是否可能是缺少 key/connection 字符串的结果?
好的,事实证明文档缺少这里的关键信息。如果您使用连接到 Azure SignalR 服务的 .NET SignalR 客户端,您需要请求 JWT 令牌并在创建集线器连接时出示它。
如果您需要代表用户进行身份验证,您可以使用 this example.
否则,您可以使用 Azure 函数等 Web API 设置“/negotiate”端点来为您检索 JWT 令牌和客户端 URL;这就是我最终为我的用例所做的。有关创建 Azure 函数以获取 JWT 令牌和 URL 的信息,请参见 here.
我创建了一个 class 来保存这两个值:
SignalRConnectionInfo.cs
public class SignalRConnectionInfo
{
[JsonProperty(PropertyName = "url")]
public string Url { get; set; }
[JsonProperty(PropertyName = "accessToken")]
public string AccessToken { get; set; }
}
我还在 SignalRService
中创建了一个方法来处理与 Azure 中网络 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
是一个静态的 class 与“ /negotiate" 附加到基础 URL.
的路径
完成所有设置后,我调用了 await hubConnection.StartAsync();
并且它 "connected"!
完成所有这些后,我设置了一个静态 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 服务团队,当然希望这对其他人有帮助!
更新:带有无服务器示例的示例 is deprecated for the management SDK (sample)。管理 SDK 使用协商服务器。
我正在尝试在我的 ASP.NET Core 3.0 Blazor(服务器端)应用程序和 Azure SignalR 服务之间建立连接。我最终会将我的 SignalR 客户端(服务)注入到一些 Blazor 组件中,以便它们实时更新我的 UI/DOM。
我的问题是,当我在集线器连接上调用 .StartAsync()
方法时收到以下消息:
Response status code does not indicate success: 404 (Not Found).
BootstrapSignalRClient.cs
此文件加载我的 SignalR 服务配置,包括 URL、连接字符串、密钥、方法名称和集线器名称。这些设置在静态 class 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()
并在应用程序配置中映射一个集线器,这样做需要某些 'configuration' 待建立的参数(即连接字符串)。
鉴于我的情况,HubConnectionBuilder
从哪里获取连接字符串或密钥以对 SignalR 服务进行身份验证?
404 消息是否可能是缺少 key/connection 字符串的结果?
好的,事实证明文档缺少这里的关键信息。如果您使用连接到 Azure SignalR 服务的 .NET SignalR 客户端,您需要请求 JWT 令牌并在创建集线器连接时出示它。
如果您需要代表用户进行身份验证,您可以使用 this example.
否则,您可以使用 Azure 函数等 Web API 设置“/negotiate”端点来为您检索 JWT 令牌和客户端 URL;这就是我最终为我的用例所做的。有关创建 Azure 函数以获取 JWT 令牌和 URL 的信息,请参见 here.
我创建了一个 class 来保存这两个值:
SignalRConnectionInfo.cs
public class SignalRConnectionInfo
{
[JsonProperty(PropertyName = "url")]
public string Url { get; set; }
[JsonProperty(PropertyName = "accessToken")]
public string AccessToken { get; set; }
}
我还在 SignalRService
中创建了一个方法来处理与 Azure 中网络 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
是一个静态的 class 与“ /negotiate" 附加到基础 URL.
完成所有设置后,我调用了 await hubConnection.StartAsync();
并且它 "connected"!
完成所有这些后,我设置了一个静态 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 服务团队,当然希望这对其他人有帮助!
更新:带有无服务器示例的示例 is deprecated for the management SDK (sample)。管理 SDK 使用协商服务器。