Blazor Server复刻SignalR聊天应用时遇Connection Id required错误
问题描述
复刻基于Blazor WebAssembly的SignalR聊天应用时改用Blazor Server App开发,点击聊天标签页时浏览器提示**"Connection Id required"**错误。
我的代码实现
Razor组件 (/room1)
@page "/room1" @using Microsoft.AspNetCore.SignalR.Client @inject NavigationManager NavigationManager @implements IDisposable <div class="form-group"> <label> User: <input @bind="userInput" /> </label> </div> <div class="form-group"> <label> Message: <input @bind="messageInput" size="50" /> </label> </div> <button @onclick="Send" disabled="@(!IsConnected)">Send</button> <hr> <ul id="messagesList"> @foreach (var message in messages) { <li>@message</li> } </ul> @code { private HubConnection hubConnection; private List<string> messages = new List<string>(); private string userInput; private string messageInput; protected override async Task OnInitializedAsync() { hubConnection = new HubConnectionBuilder() .WithUrl(NavigationManager.ToAbsoluteUri("/chathub")) .Build(); hubConnection.On<string, string>("ReceiveMessage", (user, message) => { var encodedMsg = $"{user}: {message}"; messages.Add(encodedMsg); StateHasChanged(); }); await hubConnection.StartAsync(); } Task Send() => hubConnection.SendAsync("SendMessage", userInput, messageInput); public bool IsConnected => hubConnection?.State == HubConnectionState.Connected; public void Dispose() { _ = hubConnection?.DisposeAsync(); } }
Chat Hub类
using Microsoft.AspNetCore.SignalR; namespace ChatBlazorApp.Server.Hubs { public class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } } }
Startup.cs类
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Linq; using ChatBlazorApp.Server.Hubs; namespace ChatBlazorApp.Server { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddSignalR(); services.AddControllersWithViews(); services.AddRazorPages(); services.AddResponseCompression(opts => { opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat( new[] { "application/octet-stream" }); }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseResponseCompression(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapControllers(); endpoints.MapHub<ChatHub>("/chathub"); endpoints.MapFallbackToFile("index.html"); }); } } }
错误原因及修复方案
核心问题
Blazor Server本身依赖一个内置的SignalR连接实现组件实时交互,自定义SignalR Client连接未做特殊配置时,会与内置连接产生冲突,触发"Connection Id required"错误。
具体修复步骤
配置自定义连接跳过协商并指定WebSocket传输
修改OnInitializedAsync中的连接构建逻辑,避免与内置连接的协商机制冲突:hubConnection = new HubConnectionBuilder() .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"), options => { options.SkipNegotiation = true; options.Transports = HttpTransportType.WebSockets; }) .Build();移除WebAssembly专属调试中间件
在Startup.cs的Configure方法中删除app.UseWebAssemblyDebugging();,该中间件仅适用于Blazor WebAssembly应用,Blazor Server使用会干扰连接逻辑。修正Blazor Server的Fallback路由
将endpoints.MapFallbackToFile("index.html");改为endpoints.MapFallbackToPage("/_Host");,这是Blazor Server应用的正确 fallback 配置。优化连接状态检查逻辑
原IsConnected字段初始化时hubConnection尚未创建,改为属性形式确保实时获取连接状态:public bool IsConnected => hubConnection?.State == HubConnectionState.Connected;添加连接异常处理(可选)
在OnInitializedAsync中加入try-catch块,避免连接失败导致组件崩溃:protected override async Task OnInitializedAsync() { hubConnection = new HubConnectionBuilder() .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"), options => { options.SkipNegotiation = true; options.Transports = HttpTransportType.WebSockets; }) .Build(); hubConnection.On<string, string>("ReceiveMessage", (user, message) => { var encodedMsg = $"{user}: {message}"; messages.Add(encodedMsg); StateHasChanged(); }); try { await hubConnection.StartAsync(); } catch (Exception ex) { messages.Add($"连接失败: {ex.Message}"); StateHasChanged(); } }
内容的提问来源于stack exchange,提问作者Rod

