.NET Core Blazor WASM无法连接WebSocket控制器求助
解决Blazor WASM WebSocket连接返回200且断点未触发的问题
核心问题分析
你遇到的Unexpected server response: 200和断点未触发,本质是路由配置错误+中间件顺序不当,导致WebSocket握手请求被当成普通HTTP请求处理,未能进入对应的WebSocket逻辑。
具体修复步骤
1. 修正控制器路由重复问题
你的控制器路由[Route("[controller]")]与Action路由[Route("[controller]/OnDataReceived")]会组合出重复路径/ShellyPlusData/ShellyPlusData/OnDataReceived,但你实际请求的是/ShellyPlusData/OnDataReceived,导致Action完全匹配失败,MVC返回默认200状态码。
修正后的控制器代码:
[AllowAnonymous] [ApiController] [Route("[controller]")] internal class ShellyPlusDataController : ControllerBase { // 去掉重复的[controller],直接指定Action路径 [HttpGet("OnDataReceived")] public async Task OnDataReceived() { if (HttpContext.WebSockets.IsWebSocketRequest) { using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); var buffer = new byte[1024 * 4]; WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { string raw = Encoding.UTF8.GetString(buffer, 0, result.Count); // 可在此添加消息处理逻辑,比如打印日志 Console.WriteLine($"收到WebSocket消息:{raw}"); result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); } await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); } else { HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest; } } }
2. 强制WebSocket中间件顺序
app.UseWebSockets()必须放在app.MapControllers()和app.MapBlazorHub()之前,否则MVC会优先处理请求,不会触发WebSocket握手检查。
修正后的Program.cs关键代码:
var builder = WebApplication.CreateBuilder(args); // 注册服务 builder.Services.AddControllers(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); // 若为WASM Hosted模式,对应调整为AddBlazorWebAssembly() var app = builder.Build(); // 必须先启用WebSocket app.UseWebSockets(); // 其他中间件(如CORS、静态文件) app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // 若需要跨域,配置CORS允许WebSocket请求 // app.UseCors(policy => // policy.WithOrigins("https://localhost:xxxx") // 替换为你的Blazor客户端地址 // .AllowAnyMethod() // .AllowAnyHeader() // .AllowCredentials()); // 最后映射控制器和Blazor Hub app.MapControllers(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run();
3. 中间件方式的修复要点
如果你想用MSDN的中间件方案,同样要确保中间件注册在MapControllers之前,并且检查路径匹配:
// 放在app.UseWebSockets()之后,app.MapControllers()之前 app.Use(async (context, next) => { if (context.Request.Path == "/ws") { if (context.WebSockets.IsWebSocketRequest) { using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await Echo(webSocket); } else { context.Response.StatusCode = StatusCodes.Status400BadRequest; } } else { await next(context); } }); // 补充Echo方法实现 async Task Echo(WebSocket webSocket) { var buffer = new byte[1024 * 4]; var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None); result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); } await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); }
验证测试
- 启动项目后,用PostMan连接正确地址:
- HTTPS环境:
wss://localhost:7220/ShellyPlusData/OnDataReceived - HTTP开发环境:
ws://localhost:5000/ShellyPlusData/OnDataReceived
- HTTPS环境:
- 检查断点是否触发,若仍失败,确认launchSettings.json中的端口与请求端口一致。
内容的提问来源于stack exchange,提问作者Cleo
相关产品推荐
相关产品推荐

