Why are messages pushed from an MVC app with SignalR not getting through to the client?

喜欢而已 提交于 2020-01-04 02:41:17

问题


I have a simple SignalR hub application, using MVC4/C# on the server end, hosted in an Azure Web Role (single instance, in the emulator, with an http input endpoint), and TypeScript compiled to JS on the client. I have a gallery of images that a number of clients may upload to, and when somebody uploads then I want any other connected clients to receive a message telling them this has happened and giving them the chance to refresh, similar to the way you are notified about a new answer to a question you are viewing here on SO.

On the server I have a method which returns a list of the items in the gallery, and another method to push messages to clients, like this:

    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;
    }

(The List function is then overridden in a derived class which passes in the type T - this works fine).

On the client, using the SignalR definition files from DefinitelyTyped I have the following 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);
    });
});

... which gives the following 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);
    });
});

Invoking my list function works perfectly. I get a response back from the hub exactly as expected. And if I kill the server process but keep the browser alive, I get errors in the console which show me that the client is trying to maintain a connection.

I added these two lines this.Caller.pushMesage("HELLO, CALLER"); PushMessage("HELLO, ALL CLIENTS"); to my List function on the server side to test the server pushing content to the client. I'm expecting them to be called before the list function returns, but this isn't happening. I've also tried calling the hub from outside, like this:

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

... but while I can see from tracing that my PushMessage function is being called, I never get anything on the client side.

What am I doing wrong?

References I've already tried include:

http://blogs.msdn.com/b/brunoterkaly/archive/2012/04/09/how-to-build-cloud-based-asynchronous-scalable-web-applications-with-near-real-time-persistent-long-running-connections-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


回答1:


This part of the code is wrong:

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);
    });
});

You need to subscribe before you call 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);
    });
});


来源:https://stackoverflow.com/questions/13490289/why-are-messages-pushed-from-an-mvc-app-with-signalr-not-getting-through-to-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!