3

我有一个简单的 SignalR 集线器应用程序,在服务器端使用 MVC4/C#,托管在 Azure Web 角色中(单个实例,在模拟器中,带有 http 输入端点),并且 TypeScript 在客户端编译为 JS。我有一个图片库,许多客户可能会上传到这些图片库,当有人上传时,我希望任何其他连接的客户都能收到一条消息,告诉他们这已经发生并让他们有机会刷新,类似于通知您的方式关于您在 SO 上查看的问题的新答案。

在服务器上,我有一个方法可以返回画廊中的项目列表,还有另一种方法可以将消息推送到客户端,如下所示:

    public virtual void PushMessage(String message)
    {
        System.Diagnostics.Debug.WriteLine("PushMessage: " + message);
        this.Clients.All.pushMessage(message);
    }

    public virtual GalleryDataResponse<T> List(String accountID, String armID, Int32 page)
    {
        GalleryDataResponse<T> response = new GalleryDataResponse<T>();
        try
        {
            IEnumerable<T> items = getAllItems(accountID, armID, page);
            if (items != null && items.Count() > 0)
            {
                response.Result = DataResponse.RESULT_DATA;
                response.Message = String.Empty;
                response.Items = items;
            }
            else
            {
                response.Result = DataResponse.RESULT_EMPTY;
                response.Message = @"There are no " + itemName + @"s in your account at the moment: " + this.Context.ConnectionId;
                response.Items = null;
            }
            this.Caller.pushMesage("HELLO, CALLER");
            PushMessage("HELLO, ALL CLIENTS");
        }
        catch (Exception ex)
        {
            response.Result = DataResponse.RESULT_ERROR;
            response.Message = ex.Message;
            response.Items = null;
        }
        return response;
    }

List然后在传入类型的派生类中重写该函数T- 这工作正常)。

在客户端,使用来自definitelyTyped 的 SignalR 定义文件,有以下 TypeScript:

var that = this;
this.connection = $.hubConnection();
this.connection.logging = true;
this.connection.id = this.gServerData.CurrentAccountID + "-" +    this.gServerData.CurrentArmID;
this.connection.start().done(() => {
    that.proxy = that.connection.createProxy(that.gServerData.DataHubName);
    that.proxy.on("pushMessage", (message) => {
        console.log("PUSHED: " + message);
        debugger;
    });
    that.proxy.invoke("List", that.gServerData.CurrentAccountID, that.gServerData.CurrentArmID, 0).done((response: IGalleryDataResponse) => {
        that.handleListResponse(response);
    });
});

...它给出了以下JavaScript:

var that = this;
this.connection = $.hubConnection();
this.connection.logging = true;
this.connection.id = this.gServerData.CurrentAccountID + "-" + this.gServerData.CurrentArmID;
this.connection.start().done(function () {
    that.proxy = that.connection.createProxy(that.gServerData.DataHubName);
    that.proxy.on("pushMessage", function (message) {
        t.Tracer.Trace("PUSHED: " + message);
    });
    that.proxy.invoke("List", that.gServerData.CurrentAccountID, that.gServerData.CurrentArmID, 0).done(function (response) {
    that.handleListResponse(response);
    });
});

调用我的列表功能非常有效。我完全按照预期从集线器收到了回复。如果我终止服务器进程但保持浏览器处于活动状态,我会在控制台中收到错误,显示客户端正在尝试保持连接。

我将这两行添加this.Caller.pushMesage("HELLO, CALLER"); PushMessage("HELLO, ALL CLIENTS");到服务器端的 List 函数中,以测试服务器将内容推送到客户端。我希望它们在列表函数返回之前被调用,但这并没有发生。我也尝试过从外部调用集线器,如下所示:

var myHub = GlobalHost.ConnectionManager.GetHubContext<MediaGalleryHub>();
myHub.Clients.pushMessage("Hello from Global.asax");

...但是虽然我可以从跟踪中看到我的 PushMessage 函数正在被调用,但我从来没有在客户端得到任何东西。

我究竟做错了什么?

我已经尝试过的参考资料包括:

http://blogs.msdn.com/b/brunoterkaly/archive/2012/04/09/how-to-build-cloud-based-asynchronous-scalable-web-applications-with-near-real-time-persistent-长时间运行的连接-with-signalr.aspx

http://msdn.microsoft.com/en-us/magazine/hh965663.aspx

https://github.com/SignalR/SignalR/wiki/Hubs

https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client-Hubs-%28No-Proxy%29

4

1 回答 1

4

这部分代码是错误的:

this.connection.start().done(() => {
    that.proxy = that.connection.createProxy(that.gServerData.DataHubName);
    that.proxy.on("pushMessage", (message) => {
        console.log("PUSHED: " + message);
        debugger;
    });
    that.proxy.invoke("List", that.gServerData.CurrentAccountID, that.gServerData.CurrentArmID, 0).done((response: IGalleryDataResponse) => {
        that.handleListResponse(response);
    });
});

您需要在调用 start 之前订阅:

that.proxy = that.connection.createProxy(that.gServerData.DataHubName);
that.proxy.on("pushMessage", (message) => {
    console.log("PUSHED: " + message);
    debugger;
});    

this.connection.start().done(() => {
    that.proxy.invoke("List", that.gServerData.CurrentAccountID, that.gServerData.CurrentArmID, 0).done((response: IGalleryDataResponse) => {
        that.handleListResponse(response);
    });
});
于 2012-11-21T09:58:18.187 回答