带SignalR的WCF服务

时间:2014-06-12 13:07:00

标签: asp.net wcf signalr

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

我想要的是现在在我的应用程序中使用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();
        }
    }
}

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

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

2 个答案:

答案 0 :(得分:13)

我同意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()。 {1}}将处理收到的信息。

初始页面着陆

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

首次与您的集线器联系,触摸WCF

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

定期更新用户的方法

SignalR使您的客户端代码不再需要不断轮询服务器以获取更新。它旨在允许您将数据推送到客户端,而不是直接询问它。这就是连接的持久性发挥作用的地方。

您可能希望创建一个包装器,以便从您的应用程序轻松地将消息发送到集线器,因为您正在使用WCF我会假设您拥有此层后面的业务逻辑,因此您需要将WCF服务扩展到您的Hub每当行动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

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

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

代码更新更新

.Net Client库(在NuGet中)为您的.net代码提供对集线器的访问权限。由于您是客户端,因此您需要连接到集线器,就像同时也是客户端的用户一样。您的集线器将充当此服务器。因此,对于.Net客户端,我假设您将设置一个内部轮询的Windows服务,或基于事件的事件,它将调用它的.Net客户端代码部分,它将到达您的集线器。您的集线器将获取所提供的信息,而不仅仅是ConnectionId或GroupId,并广泛投射用户(可能在网站上,因此它将是JS客户端)一种方法,将更新用户客户端的前端。基本上我在&#34;简要解释&#34;。

下提到的

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

现在,我实际上会说你的javascript正确而不是纠正集线器代码。为什么?因为在客户端的JS中有一个名为&#34; refreshChart()&#34;当您让服务器伸出并更新客户端时,可以重复使用。

所以我建议,删除与JS done语句中更新仪表板相关的任何内容。如果你想向用户做一个通知或其他什么,但不要更新网格。

现在创建一个名为&#34; refreshChart&#34;的JS客户端函数,注意小写R,你可以用c#中的一个大R来调用它,但是js库会小写它,所以当你使函数有它时将收到您的信息中心信息。

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

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

答案 1 :(得分:9)

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

来自client

    hub.VisitingDashBoard();
<{1}}方法中的hub上的

VisitingDashBoard

当然,您的var data = wcfClient.GetDashboardData()//may be pass the user id from the context Clients.Caller.UpdateDashboard(data) 将拥有client来电

的处理程序