在同一台服务器上的Windows服务中发送来自运行在ASP.NET MVC应用程序内部的SignalR广播

3
我有一个使用SignalR hubs向网站用户发送消息的ASP.NET网站。
我在我的业务层中调用hubs的代码,并使用依赖注入将hubs的实例从我的ASP.NET应用程序注入到我的业务层中。
我遇到的问题是,当我在Windows服务中使用我的业务层时,我不知道如何获取hubs的实例。
是否可以从服务器上“挂钩”到正在运行于我的ASP.NET应用程序中的现有SignalR hubs,并从我的Windows服务发送广播?
我意识到我可以使用以下代码作为客户端在我的Windows服务中连接,但这是错误的方法,我想要从服务器发送广播...
// This code enables a client connection
var connection = new HubConnection("http://localhost:3537/");
IHubProxy myHub = connection.CreateHubProxy("NotificationHub");

connection.Start().Wait(); 

myHub.Invoke("setNotificationCount", "5");

你列出的代码是作为客户端连接还是尝试从服务器广播? - Pseudonym
所列代码是从C#应用程序作为客户端连接。我想要连接,但希望能够从在同一服务器上运行的Windows服务端广播。 - Luke
啊,这比我想象的要棘手一些,嗯,我发了一个答案,但现在不确定它会有多大帮助…还在继续研究中。 - Pseudonym
没问题,谢谢你抽出时间来回答 :o) - Luke
让我们在聊天中继续这个讨论 - Pseudonym
显示剩余2条评论
2个回答

1

编辑:根据我们的讨论,我对问题的理解如下:

问题: 有一个现有项目可以访问SignalR客户端,并且该项目需要响应在同一服务器上运行的Windows服务事件。

我的解决方案: 我将构建或利用WebAPI项目作为服务和服务器项目之间的中间人。服务可以调用WebAPI方法,这些方法可以访问您的业务逻辑,然后根据需要更新SignalR客户端。这还具有使用Microsoft提供的内置保护的优点(即任何身份验证方案:表单、Windows等)。


The way this tutorial explains it is that in order to broadcast to clients, you first need to get references to all of the connected clients. GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients 是返回客户端列表的示例。 从那里开始,你需要像这样做(再次使用他们的示例):Clients.All.SomeClientMethod(string aParameter)

感谢您抽出时间回答。这在ASP.NET应用程序内是可能的,但不幸的是无法从不同的项目中实现,例如Windows服务器。 - Luke
是的,我看到了你的评论,我正在研究它。 - Pseudonym

1

您的Hub托管在ASP.NET应用程序中。因此,没有直接从Windows服务进行广播的方法...除非使用SignalR的scaleout功能...

解决方案1(不使用scaleout - 首选)

Windows服务作为客户端连接到运行在APS.NET应用程序中的Hub(hub1),并调用特殊的Hub方法,该方法向所有客户端广播消息。当然,这种方法可以被普通(浏览器)客户端滥用。为了消除这个问题,您可以在ASP.NET应用程序中创建另一个Hub(hub2),将方法放置在此处,并使用GlobalHost.ConnectionManager.GetHubContext<hub1>()来向连接到hub1的所有客户端广播。Hub2可以通过授权保护,因此只有Windows服务可以使用它。 由于您已经使用DI容器并将Hub注入到业务逻辑中,因此定义公共接口(INotificationService)并创建两个不同的实现应该很容易 - 第一个将在ASP.NET应用程序中使用(使用Hub1进行实际通知),第二个将在Windows服务中使用并使用Hub2将通知传递给ASP.NET应用程序。从BL的角度来看,这是相同的事情...

OFC for Win Service -> ASP.NET通讯,您可以使用任何其他通讯技术,如MVC或WebAPI(正如@Pseudonym所建议的),而不仅仅是SignalR。

解决方案2

如果这对您来说不是解决方案,那么还有另一个想法。 我认为 SignalR scaleout feature可以在这里被(误)用。只需将您的hub1同时托管在ASP.NETWindows服务中(使用不同的URL和端口!)。即使客户端只直接连接到ASP.NET应用程序,运行在Windows服务内部的代码仍然能够向它们广播消息(消息通过scaleout消息总线传递,然后传递到ASP.NET应用程序,最后传递到客户端)。

如果使用扩展性更加复杂(需要 SQL Server\Redis 或任何其他 SignalR 后台 + 延迟等等),您可能想要锁定 Windows 服务中心,以便客户端无法直接连接并运行 hub1 方法(我不确定如何做到这一点 - 一个想法是使用另一个具有相同名称(HubNameAttribute)和空方法 + 授权的 hub 实现,以便没有人可以连接它)。总之,这会带来更多麻烦,您应该有足够充分的理由选择这种路线...


谢谢,我打算连接到SignalR Hub,或者在那里使用一些基本的WebAPI安全性。 - Luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接