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

.NET5 Blazor Server集成SignalR+Azure AD统计在线用户报错

问题根因

抛出JsonReaderException: '<' is an invalid start of a value和InvalidDataException: Invalid negotiation response received的核心原因是:SignalR客户端发起连接协商(negotiate)请求时,没有收到预期的JSON格式响应,反而收到了HTML格式内容(通常是404错误页、认证重定向页,这类内容都以<html>标签开头,System.Text.Json读取到第一个字符<就会直接抛出解析错误)。
你现有代码里有两处直接触发该问题的错误:

  • 前后端Hub路径不匹配:服务端Startup中映射的Hub地址是/peoplehub,但前端组件初始化连接时写的地址是/chathub,请求打到不存在的路由,服务端返回HTML格式的404页面,直接触发解析失败。
  • Hub类名拼写错误:定义Hub时类名写为PeoplHub(缺失字母e),和MapHub泛型参数传入的PeopleHub不一致,即便路径修正也无法匹配到正确的Hub实例。
分步修复方案

1. 修正命名、路径不匹配问题

首先修正Hub类的拼写错误,确保类名和服务端注册时的泛型参数完全一致:

// 补上类名缺失的字母e,添加public访问修饰符
public class PeopleHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

然后修改Index.razor中的Hub连接地址,和服务端映射路径保持一致:

hubConnection = new HubConnectionBuilder()
    // 将错误的/chathub替换为服务端映射的/peoplehub
    .WithUrl(NavigationManager.ToAbsoluteUri("/peoplehub"))
    .Build();

hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
    var encodedMsg = $"{user}: {message}";
    messages.Add(encodedMsg);
    InvokeAsync(StateHasChanged);
});
await hubConnection.StartAsync();

2. 修复Azure AD认证拦截问题

你的站点全站启用了Azure AD认证,未携带有效认证凭据的请求会被重定向到Azure AD登录页(同样是HTML格式),也会触发解析错误。如果要求只有登录用户才能连接Hub,不需要给Hub加匿名访问,只需要在构建连接时配置携带认证凭据,同时调整中间件顺序:

  • 确保app.UseResponseCompression()放在所有其他业务中间件的最前面(仅放在异常处理中间件之后),避免压缩逻辑干扰SignalR响应格式。
  • 给Hub路由配置认证规则,避免未登录请求被302重定向到登录页:
app.UseEndpoints(endpoints =>
{
    // 原有MapHub配置补充认证规则,不要加AllowAnonymous
    endpoints.MapHub<PeopleHub>("/peoplehub").RequireAuthorization();
    // 其他原有路由配置...
});
  • 客户端构建Hub连接时开启凭据携带:
hubConnection = new HubConnectionBuilder()
    .WithUrl(NavigationManager.ToAbsoluteUri("/peoplehub"), options =>
    {
        options.UseDefaultCredentials = true;
    })
    .Build();

3. 优化连接释放逻辑

现有DisposeAsync实现没有判断连接状态,连接处于连接中/断开中状态时直接释放会抛出异常,补充状态判断:

public async ValueTask DisposeAsync()
{
    if (hubConnection is not null)
    {
        if (hubConnection.State == HubConnectionState.Connected || hubConnection.State == HubConnectionState.Connecting)
        {
            await hubConnection.StopAsync();
        }
        await hubConnection.DisposeAsync();
    }
}
验证方法

修改完成后重启应用,打开浏览器开发者工具的网络面板,筛选negotiate请求,确认该请求响应状态为200,响应内容为包含connectionId、availableTransports字段的JSON格式,即表示连接正常,不会再抛出之前的解析错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:15:51