使用 signalr 将数据存储在 asp.net 中

store data in asp.net with signalr

我正在尝试使用 signalr 在 asp.net 应用程序中存储数据。举例说明我的问题。

我有一个集线器,可以通知控件用户已连接并发送他的 ID。

public static event EventHandler<IdEventArgs> userConnected;

public void Connected()
{
    Debug.WriteLine("Hub Connected Method");
    var id = Context.ConnectionId;

    userConnected(this, new IdEventArgs(id));
}

然后我的控制器将事件处理程序添加到集线器

    public ActionResult Index()
    {
        LoadingHub.userConnected += new EventHandler<IdEventArgs>(UserConnected);

        return View();
    }

最后是我的方法,应该保存获取的数据

    private void UserConnected(object sender, IdEventArgs e)
    {
        Debug.WriteLine("User Connected with Id: " + e.Id);

        //To do:
        //save data
    }

我尝试保存到 Session,但此处的 Session 对象为空。我遇到了用户配置文件,也许这将是一个很好的解决方案——当用户连接以在内部存储数据时,以及当他断开连接以销毁所述配置文件时,是否可以创建新的配置文件?或者完全不同的方法在这里更合适?

如评论中所述,Session 不适用于 SignalR。我会说你有两个主要选择:

  • 使用 state 功能,如 here 所述,这样您的数据将通过连接来回传输,但只要连接有效(适用于小负载,如果您不介意客户端访问该信息)
  • 使用依赖注入(检查here)将服务传递给您的集线器,您可以随意定义其接口(它可以是一对简单的get/set 方法),其实现可能很多,从用于开发场景的内存中 static(不一定是字面上的)字典到任何类型的您想要用于提供水平可伸缩性(如果需要)的持久存储。一开始有点费力,但后来变得非常容易和灵活

我将举例说明您需要创建单例服务来为用户保持连接的解决方案。很容易修改以保存任何类型的数据。只需要在需要的服务中注入它,controller

public class ConnectionMapping<TConnectionKey>
{
    private readonly Dictionary<TConnectionKey, HashSet<string>> _connections =
        new Dictionary<TConnectionKey, HashSet<string>>();

    public int Count
    {
        get
        {
            return _connections.Count;
        }
    }

    public void Add(TConnectionKey key, string connectionId)
    {
        lock (_connections)
        {
            HashSet<string> connections;
            if (!_connections.TryGetValue(key, out connections))
            {
                connections = new HashSet<string>();
                _connections.Add(key, connections);
            }

            lock (connections)
            {
                connections.Add(connectionId);
            }
        }
    }

    public IReadOnlyList<string> GetConnections(TConnectionKey key)
    {
        HashSet<string> connections;
        if (_connections.TryGetValue(key, out connections))
        {
            return new List<string>(connections);
        }

        return new List<string>();
    }

    public void Remove(TConnectionKey key, string connectionId)
    {
        lock (_connections)
        {
            HashSet<string> connections;
            if (!_connections.TryGetValue(key, out connections))
            {
                return;
            }

            lock (connections)
            {
                connections.Remove(connectionId);

                if (connections.Count == 0)
                {
                    _connections.Remove(key);
                }
            }
        }
    }

    public string ToJson()
    {
        var entries = _connections.Select(d =>
            string.Format("\"{0}\": [\"{1}\"]", d.Key, string.Join(",", d.Value)));
        return "{" + string.Join(",", entries) + "}";
    }
}