You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

验证测试

  1. 启动项目后,用PostMan连接正确地址:
    • HTTPS环境:wss://localhost:7220/ShellyPlusData/OnDataReceived
    • HTTP开发环境:ws://localhost:5000/ShellyPlusData/OnDataReceived
  2. 检查断点是否触发,若仍失败,确认launchSettings.json中的端口与请求端口一致。

内容的提问来源于stack exchange,提问作者Cleo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:44:57