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

.NET 6下SignalR无法从UI层传递登录用户ID获取对应数据的问题

.NET 6下SignalR无法从UI层传递登录用户ID获取对应数据的问题

看起来你遇到的情况有点棘手:Swagger调用SignalR方法完全正常,但从前端页面调用就报错"Failed to invoke 'SendBasket' due to an error on the server",而且ViewBag里的UserId明明是对的。别着急,咱们一步步排查问题所在:

第一步:先搞清楚服务器端到底出了什么错

前端的错误提示太笼统了,咱们得先拿到服务器端的具体异常信息。你可以在SignalRHub的SendBasket方法里加日志或者捕获异常,看看是参数没传对,还是调用_ebasketService的时候出了问题:

public class SignalRHub : Hub
{
    private readonly IEFBasketService _ebasketService;
    private readonly ILogger<SignalRHub> _logger; // 注入日志组件

    public SignalRHub(IEFBasketService ebasketService, ILogger<SignalRHub> logger)
    {
        _ebasketService = ebasketService;
        _logger = logger;
    }

    public async Task SendBasket(int userId)
    {
        try
        {
            // 先记录收到的用户ID,确认参数是否正确传递
            _logger.LogInformation("收到SendBasket请求,用户ID:{UserId}", userId);
            
            var basketCount = await _ebasketService.GetByUserIdBasketQuantity(userId);
            _logger.LogInformation("获取到购物车数量:{Count},用户ID:{UserId}", basketCount, userId);
            
            await Clients.All.SendAsync("ReceiveBasketCount", basketCount);
        }
        catch (Exception ex)
        {
            // 记录详细错误信息
            _logger.LogError(ex, "处理SendBasket请求出错,用户ID:{UserId}", userId);
            throw; // 重新抛出异常,让前端能看到具体错误
        }
    }
}

添加完日志后,重启项目再测试,然后去看服务器的日志(比如控制台输出或者日志文件),就能知道具体是哪里出问题了——是userId传成了0/无效值,还是服务调用抛了异常?

第二步:确认前端拿到的UserId是否真的正确

虽然你说ViewBag.UserId是对的,但咱们得确认前端DOM里确实渲染了正确的值,而且JS能拿到它:

  1. 在浏览器打开页面,按F12打开开发者工具,找到#basketCount元素,查看它的data-user-id属性是否真的有值(比如是不是1而不是空或者字符串)。
  2. 在JS代码里加个console.log,打印拿到的userId:
connection.start().then(() => {
    $("#connstatus").text(connection.state);

    // UserId'yi HTML'den alıyoruz
    var userId = $("#basketCount").data("user-id");
    console.log("从DOM获取的用户ID:", userId); // 打印出来看看

    setInterval(() => {
        connection.invoke("SendBasket", userId).catch(err => console.error(err.toString()));
    }, 1000); 
}).catch((err) => { console.log(err) });

如果控制台打印的userId是undefined,那说明JS没有正确拿到DOM元素的值——可能是元素渲染时机的问题?不过你用了$(document).ready(),理论上DOM应该加载完了,但也可以试试把script放到#basketCount元素之后,或者用$(window).load()确保所有元素都渲染完毕。

另外要注意:如果ViewBag.UserId是字符串类型(比如数据库里是Guid或者字符串ID),但服务器端方法参数是int,传递的时候就会报错。这种情况要把服务器端的参数类型改成对应的类型(比如string userId),或者确保前端传递的是有效的数字。

第三步:简化前端调用逻辑,排除干扰

你现在用了setInterval每秒调用一次,先暂时去掉它,改成单次调用测试,看看是不是定时调用的问题:

connection.start().then(() => {
    $("#connstatus").text(connection.state);

    var userId = $("#basketCount").data("user-id");
    console.log("用户ID:", userId);

    // 先只调用一次,看看是否成功
    connection.invoke("SendBasket", userId)
        .then(() => console.log("SendBasket调用成功!"))
        .catch(err => console.error("调用失败:", err.toString()));

}).catch((err) => { console.log("连接失败:", err) });

如果单次调用成功,那可能是定时调用太频繁导致服务器压力大,或者有其他并发问题;如果还是失败,那回到第一步看服务器日志的具体错误。

第四步:检查CORS和连接地址

虽然Swagger能调用,但也可以再确认一下CORS配置是否完全兼容SignalR:你的配置看起来没问题,但可以试试把SetIsOriginAllowed((host) => true)改成AllowAnyOrigin()(不过前者更灵活),另外确保前端的SignalR连接地址和API的地址完全匹配(比如HTTP/HTTPS、端口号是否一致)。

按照这些步骤排查,应该能很快找到问题所在。比如大概率是前端传递的userId有问题(比如undefined或者类型不匹配),或者服务器端调用服务时抛出了异常。

备注:内容来源于stack exchange,提问作者Halil Kürel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:08:09