如何在应用程序成员与Web API和Signalr Hub之间设计更好的通信

时间:2014-01-08 20:40:12

标签: asp.net-mvc asp.net-web-api signalr

我正在一个需要实时与用户沟通的项目中工作。基本上我正在关注“在web api上同步页面”路径,该路径在this video中引入(也是Brad Wilson有一个很好的视频)和repository here for video

我的问题是将应用程序成员映射到由Signalr生成的ConnectionIds。

我曾经在数据库表中保存每个信号器连接ID,如:

  

ConnectionID

     

会员ID

     

ConnectionStatusID - >连接(1),断开连接(2),重新连接(3)

我在大多数请求中提取了成员的连接ID。

然后我决定改变这个设计。现在,我在OnConnected和OnDisconnected上使用唯一字符串对每个成员进行分组,如下所示:

public override Task OnConnected()
{
    Groups.Add(this.Context.ConnectionId, string.Format("MyHub_{0}",HubUser.MemberID));
    return base.OnConnected();
}

public override Task OnDisconnected()
{
    Groups.Remove(this.Context.ConnectionId, string.Format("MyHub_{0}",HubUser.MemberID));
    return base.OnConnected();
}

现在我没有从数据库中获取有关成员连接ID的任何内容。它仅适用于Web API,用于在浏览器选项卡之间进行同步。

我只是展示了我如何处理传入的请求并在Web API中使用Hub:

public HttpResponseMessage Example()
{
    string msg = "Example to all";
    //some other process

    //Hub is an instance of a IHubContext

    Hub.Clients.Group(string.Format("MyHub_{0}", HubUser.MemberID)).example(msg);

    return Request.CreateResponse(HttpStatusCode.OK, msg);
}

您认为哪一种是使用Signalr的有效方法。你会建议什么可能比这些更好。在集线器和WebApi之间建立依赖关系是一个很好的设计选择。

此外,项目将部署到多个服务器,Load Balancer将在他们面前工作(我将使用Sql Backplane)。很少有项目必须与Web API通信,间接与集线器通信。

1 个答案:

答案 0 :(得分:1)

我喜欢你的第二个解决方案,因为它应该需要更少的数据库查询。 SignalR发送到组的效率不低于发送到连接ID的效率。您只需确保您的群组名称(HubUser.MemberID)是唯一且不可欺骗的。

在SignalR 2.0中,我们使这种模式变得更加容易:http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider

如果您的用户的MemberID与其IPrincipal.Identity.Name匹配,那么您只需更改所有代码即可使用Clients.User(HubUser.MemberID)...

如果您不想将SignalR用户ID基于请求的IPrincipal,您可以提供自己的IUserIdProvider并使用SignalR的依赖性解析器注入它。

http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection