【问题标题】:Sharing ServiceStack ICacheClient with SignalR与 SignalR 共享 ServiceStack ICacheClient
【发布时间】:2024-01-11 21:00:01
【问题描述】:

我正在尝试在 ServiceStack OOB ICacheClient 和 SignalR Hub 之间共享缓存中的元素,但是当我尝试在 OnDisconnected 事件中获取用户会话时出现以下错误

仅支持通过单例访问的 ASP.NET 请求

我在 OnConnected 事件中访问会话没有问题,到目前为止,这就是我所做的:

public class HubService:Hub
{
    private readonly IUserRepository _userRepository;
    private readonly ICacheClient _cacheClient;

    public HubService(IUserRepository userRepository,ICacheClient cacheClient)
    {
        _userRepository = userRepository;
        _cacheClient = cacheClient;
    }

    public override System.Threading.Tasks.Task OnConnected()
    {
        var session = _cacheClient.SessionAs<AuthUserSession>();
        //Some Code, but No error here
        return base.OnConnected();
    }

    public override System.Threading.Tasks.Task OnDisconnected()
    {
        var session = _cacheClient.SessionAs<AuthUserSession>();
        return base.OnDisconnected();
    }
}

我正在使用简单的注入器,并且我的 ICacheClient 被注册为单例:

 Container.RegisterSingle<ICacheClient>(()=>new MemoryCacheClient());

问题是如何在 SS 中将 requests 注册为单例?我在 SignalR 活动中遗漏了什么?

编辑:

我试图在 SS 中为 register requests 解释是因为如果有可能使用容器注册 SS IHttpRequest 并由于异常消息将生活方式设置为单例,那么它看起来像 httpContext 和OnDisconnected 事件导致 IHttprequest 为空

SS代码如下:

public static string GetSessionId(IHttpRequest httpReq = null)
{
    if (httpReq == null && HttpContext.Current == null)
        throw new NotImplementedException(OnlyAspNet); //message
        httpReq = httpReq ?? HttpContext.Current.Request.ToRequest();
        return httpReq.GetSessionId();
}

我要做的是使用 ICacheClient 存储已连接用户的列表,我只想在用户断开连接时从列表中删除 connectionID。

编辑: 好像根据danludwig post

“关于 SignalR 有一个有趣的事情......当客户端与 集线器(例如通过关闭他们的浏览器窗口),它将创建一个 Hub 类的新实例,以便调用 OnDisconnected()。 发生这种情况时,HttpContext.Current 为空。因此,如果此 Hub 有任何依赖项 > 按 Web 请求注册,则可能会出现问题。”

上面的描述完全符合我的情况

【问题讨论】:

  • 我认为 Simple Injector 中的注册与任何其他容器中的注册没有太大不同,所以如果有人可以为不同的容器回答这个问题,请这样做。我将使用 Simple Injector 详细信息(并投票)更新该答案。不幸的是,我目前无法回答这个问题,因为我不知道“注册请求”是什么意思。

标签: c# dependency-injection servicestack signalr simple-injector


【解决方案1】:

我不是 SingalR 专家,但根据我对它和简单注入器的经验,我认为您无法在 OnDisconnected 期间访问 Session(或 Request,或 HttpContext)。但是,如果您考虑一下,这是有道理的——当客户端与集线器断开连接时,SignalR 不再有权访问会话 ID,没有请求,不再与客户端通信。 OnDisconnected 基本上是在告诉您“在这里,对这个 ConnectionId 做一些事情,因为它所属的客户端已经消失了。”授予用户可能会回来,然后您可以在 OnReconnected 期间访问网络好东西(会话、请求等,只要您是 IIS 托管的)。

在这 3 个集线器连接事件期间,我在获取一些简单的注入器依赖项以具有正确的生命周期范围时遇到了类似的问题。我想为每个 http 请求注册 1 个依赖项,它适用于除 OnDisconnected 之外的所有内容。因此,我不得不在可能的情况下使 SI 容器使用 http 请求,但在 OnDisconnected 事件期间需要依赖项时使用新的生命周期范围。如果您愿意阅读它,我有一个帖子here 描述了我的经历。祝你好运。

【讨论】:

  • 感谢您的回答,完全有道理,因为我得到了 IHttpRequest 的空引用,我会看看你的帖子,我会告诉你进展如何。