【问题标题】:WCF Service with SignalR带有 SignalR 的 WCF 服务
【发布时间】:2014-08-02 19:51:06
【问题描述】:

我有一个 Web 应用程序,它的仪表板上的图表很少。图表数据在客户端调用 WCF 服务方法的 document.ready 函数中获取。

我现在想要的是在我的应用程序中使用 SignalR。我对 SignalR 真的很陌生。我如何从 SignalR Hub 调用 WCF 方法,或者您可以说,我希望 WCF 服务每隔一分钟将数据推送到客户端,而不是从服务器中提取数据。

signalR 和 WCF 服务之间有没有一种通信方式。

另一种方法是强制客户端每分钟向 WCF 服务请求数据。

任何帮助将不胜感激。

到目前为止,我已经完成了关注。

我的仪表板页面上的客户端功能

<script src="Scripts/jquery.signalR-2.0.3.min.js"></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="/signalr/hubs"></script>
<a id="refresh">Refresh</a>
    $(function() {
            var dashboardHubProxy = $.connection.dashboardHub;
            $.connection.hub.start().done(function() {
                // dashboardHubProxy.server.refreshClient(parameters);
                $("#refresh").click(function() {
                    dashboardHubProxy.server.refreshClient(parameters);
                });
            });
            dashboardHubProxy.client.refreshChart = function (chartData) {
                debugger;
                DrawChart(chartData, 'Hourly Call Count For Last ' + Duration + ' Days', '#chartHourly', 'StackedAreaChart');
            };
        });

而我的 Dashboard Hub 类如下

public class DashboardHub : Hub
{
    private readonly ReportService ReportService = new ReportService();


    public void RefreshClient(string parameters)
    {
        var chartData = ReportService.GenerateHourlyCallsTrendGraphicalReport(parameters);
        Clients.All.refreshChart(chartData);
    }
}

我的 SignalR 启动类如下

[assembly: OwinStartup(typeof(CallsPortalWeb.Startup), "Configuration")]
namespace CallsPortalWeb
{
    public static class Startup
    {
        public static void Configuration(IAppBuilder app)
        {
            ConfigureSignalR(app);
        }
        public static void ConfigureSignalR(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

当我在集线器上单击刷新按钮和 RefreshClient 方法上的调试器时,调试器无法访问该方法,这意味着我无法调用 SignalR 的服务器端方法。

web.config 中有什么需要做的吗?

【问题讨论】:

  • 我唯一真正想要的就是能够让服务器将数据推送到仪表板
  • 很遗憾,我们不会为您编写代码,您可以提供代码,我们可以帮助澄清它并磨练您的尝试。我在下面提供的链接将解释 SignalR,它不是神奇地发生的事情,您必须阅读并了解它,我提供了资源来做到这一点。如果您没有提供您尝试过的代码,那么您将无法找到您正在寻找的答案,因为我们没有任何可以指导您的内容。
  • 为了进一步详细说明我的评论,您是否知道 SignalR 本身不会保留连接?您打算如何存储谁已连接以及谁属于哪个组以及谁将获得您想要发送到仪表板的这些更新,您是使用静态集合还是持久保存在数据库中,您将使用多台服务器?这个仪表板用户是特定的,还是您将数据发送到全世界​​? signalR 背后还有更多内容,而不仅仅是发送消息并从服务器更新 ui。
  • @Tony 我将从数据库中获取数据。仪表板是用户特定的。对于登录的人。我正在考虑仅为呼叫者客户端更新仪表板。如果我有一些误解,请详细说明。
  • 有人可以解释如何通过 WCF 端点托管 SighalR 集线器吗?

标签: asp.net wcf signalr


【解决方案1】:

我同意 AD.Net 的评论。不过,稍微详细一点,SignalR 集线器可以直接托管在您的 Web 项目中,就像使用控制器一样。还有一个包,因此您可以自己托管 SignalR 库,这样它就可以自己充当服务。无论哪种方式,您都需要先点击 SignalR 集线器,因为这是它的通信方式,然后您可以从集线器内调用 WCF 服务方法。

简要说明

您的 HUB 将具有供您的 USER 客户端和 WCF 客户端使用的方法。您可以使用UserConnected() 之类的东西让用户调用并设置您的连接日志记录。然后,WCF 服务可能会使用 UpdateUserStats(Guid connnectionId, UserStats stats) 调用您的 HUB,而后者又会直接调用 USER 客户端并提供传入的统计信息,就像 Clients.Client(connectionId).updateStats(stats) 这样在 USERS 客户端上会有一个名为 updateStats() 的方法处理收到的信息。

初始页面登陆

AD.Net 提供的是用户登陆页面时将调用的基本代码。此时,您需要记录与该用户相关的 ConnectionId,以便您可以直接与他们联系。

第一次接触你的集线器并接触 WCF

从您的 Hub 中,您可以像在任何普通 C# 代码中通常那样调用 WCF 服务来获取您的数据或执行操作并将其返回给您的用户。

定期更新用户的方法

SignalR 消除了您的客户端代码必须不断轮询服务器以获取更新的需要。它旨在允许您将数据推送到客户端,而无需他们直接请求。这就是连接的持久性发挥作用的地方。

您可能希望创建一个包装器,以便轻松地将消息从您的应用程序发送到集线器,因为您使用的是 WCF,我假设您的业务逻辑位于该层后面,因此您希望 WCF 服务能够连接到您的集线器每当动作 X 发生时。您可以通过使用客户端 C# 代码来做到这一点,因为在这种情况下,您的客户端实际上是用户和 WCF 服务。 使用聊天应用程序,其他用户基本上是在做您希望 WCF 服务做的事情,即向其他客户端发送消息。

使用示例

您正在经营一家在线商店。仪表板显示当天有多少订单。因此,当用户下新订单时,您将调用集线器以发送消息以更新订购的产品。您可以通过将其发送到您配置的管理员组来执行此操作,仪表板上的任何管理员都会收到该消息。尽管如果这些统计信息是非常特定于用户的,那么您更有可能转而进入数据库,找到用户已连接的 ConnectionId 并将更新消息直接发送到该 connectionid。

WCF 客户端代码示例

如果您想要一些代码,这直接来自 MS 站点,用于连接 .net 客户端。您可以在 WCF 服务中使用它,或者在您计划连接然后向用户发送更新的代码中的任何位置使用它。

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

这是直接指向 .Net 客户端部分的链接:http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-net-client

我相信您已经看过此链接,但它确实包含您开始使用所需的所有有用信息。 http://www.asp.net/signalr

这是一个更直接的链接,可以为您使用代码。 http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server

添加:这是一个专门针对具有 SignalR 的仪表板及其轮询的博客。 http://solomon-t.blogspot.com/2012/12/signalr-and-interval-polling-for.html

添加:这是管理用户 signalR 连接的页面。 http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections

更新代码

.Net 客户端库(在 NuGet 中)使您的 .net 代码可以访问集线器。由于您是客户端,因此您需要连接到集线器,就像同时也是客户端的用户一样。您的集线器将充当此服务器。因此,对于 .Net 客户端,我假设您将设置一个内部轮询的 Windows 服务,或者基于事件的调用它的 .Net 客户端代码部分,该部分将到达您的集线器。您的集线器将获取提供的信息,很可能是 ConnectionId 或 GroupId 并广播用户(可能在网站上,因此它将是 JS 客户端)一种可以更新用户客户端前端的方法。基本上是我在“简要说明”下提到的。

现在,直接回复您发布的代码。那是Javascript,我希望像您一样进行连接。在初始连接时更新图表也很好。如果这是所有代码 signalR 明智的,尽管您缺少处理刷新的客户端方法。从技术上讲,您可以只返回该数据并使用它,而不是调用 Clients.Caller.RefreshChart(),这就是您的 javascript 现在正在做的事情。您正在返回 void 但它正在等待您的约会。

现在,我实际上会说更正您的 javascript 而不是更正集线器代码。为什么?因为在您的客户端上有一个名为“refreshChart()”的 JS 方法可以在您让服务器接触并更新客户端时重复使用。

所以我建议,在你的 JS done 语句中删除与更新仪表板相关的任何内容。如果您想向用户发送通知或其他操作,这很好但不要更新网格。

现在创建一个名为“refreshChart”的 JS 客户端函数,注意小写的 R,你可以在 C# 中用大 R 调用它,但 js 库会将它小写,所以当你创建函数时它会收到你的仪表板信息.

现在,在服务器轮询或执行某些操作时,您的 WCF 将调用集线器上的一个方法,即“UpdateDashboar(connectionId,dashInfo)”,然后该方法在其中调用“refreshChart”就像您在 RefreshClient 方法中所做的那样,接受而不是执行 Clients.Caller 您将使用 Clients.Client(connectionId).refreshChart(chartInfo)。

您的代码无法正常工作的直接原因是您需要将该 Void 转换为您期望返回的类型。如果其余部分编码正确,您将更新一次。如果您希望它不断更新,您将需要实现我提到的其他逻辑。这就是为什么我再次询问您如何保持联系的原因。如果您不确定我在说什么,我添加了一个链接来帮助您。

【讨论】:

  • 我已将代码添加到我的问题中,以显示我到目前为止所做的工作
  • 我再次编辑了我的代码,但我仍然无法调用集线器上的服务器端方法。你能检查并指导我完成它吗?
【解决方案2】:

您应该使用SignalR Hub 将数据推送到客户端。您的hub 可以使用WCF service(与您的client 相同的方式)来获取数据。

来自client

    hub.VisitingDashBoard();

关于hub 中的VisitingDashBoard 方法:

var data = wcfClient.GetDashboardData()//may be pass the user id from the context
         Clients.Caller.UpdateDashboard(data)

当然,您的 client 将有一个处理 UpdateDashboard 调用的处理程序

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-29
    • 2018-12-10
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多