locked
Call client method from server hub does not work RRS feed

  • Question

  • User-1708450884 posted

    Hi there

    I am new to SignalR and tried something that does not work. I am using Visual Studio 2019, Asp.Net MVC 5 and .Net framework 4.7.2. The scripts for SignalR are in version 2.4.1. and the jquery scripts in 1.6.4. I established a connection to an external hub, that worked. I also tried the chat example methods from Asp.Net, these methods also work. But then I tried to call my client method from the server without calling a server method myself before. And that does not work. Let me show you what I mean:

    Here is my client side: 

     $(function () {
                var hubconn = $.hubConnection('http://localhost:9002/signalr');
                var notiProxy = hubconn.createHubProxy('CoreHub');
                notiProxy.on('broadcastMessage', (name, connectionid, message) => {
                    console.log('Invocation of client method broadcastMessage in CoreHub succeeded');
            //        // Html encode display name and message.
                    var encodedName = $('<div />').text(name).html();
                    var encodedID = $('<div />').text(connectionid).html();
                    var encodedMsg = $('<div />').text(message).html();
                    // Add the message to the page.
                    $('#discussion').append('<li><strong>' + encodedName
                        + '</strong>:&nbsp;&nbsp;' + encodedID + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
                });
                // Set initial focus to message input box.
                $('#message').focus();
                // Start the connection.
                hubconn.start().done(function () {
                    $('#sendmessage').click(function () {
                        // Call the Send method on the hub.
                        notiProxy.invoke('Send', $('#displayname').val(), $('#message').val()).done(function () {
                            console.log('Invocation of Send Method in CoreHub succeeded');
                        
                        }).fail(function (error) {
                            console.log('Invocation of CoreHub failed. Error: ' + error);
                        });
                        
                        // Clear text box and reset focus for next comment.
                        $('#message').val('').focus();
                    });
                });
            });

    And here is the server code for the hub (running in a console application):

    /// <summary>
            /// Sample method to test the service.
            /// </summary>
            /// 
            /// <param name="name"></param>
            /// <param name="message"></param>
            /// 
            public void Send(string name, string message)
            {
                string connectionId = this.Context.ConnectionId;
                
                Clients.All.broadcastMessage(name, connectionId, message);    
            }
    
    
    So far, so good. This code works fine. But now I tried to call a method UpdateTaskState on the client side from the server like this:
     $(function () {
                var hubconn = $.hubConnection('http://localhost:9002/signalr');
                var notiProxy = hubconn.createHubProxy('CoreHub');
               
                notiProxy.on('UpdateTaskState', (processInstanceLabel, taskLabel, previousTaskState, currentTaskState) => {
                    console.log('Invocation of client method UpdateTaskState in CoreHub succeeded');
                    //        // Html encode display name and message.
                    var encodedName = $('<div />').text(processInstanceLabel).html();
                    var encodedID = $('<div />').text(taskLabel).html();
                    var encodedMsg = $('<div />').text(currentTaskState).html();
                    // Add the message to the page.
                    $('#discussion').append('<li><strong>' + encodedName
                        + '</strong>:&nbsp;&nbsp;' + encodedID + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
                });
                // Start the connection.
                hubconn.start().done(function () {
                    $('#sendmessage').click(function () {
                        // Call the Send method on the hub.
                        notiProxy.invoke('Send', $('#displayname').val(), $('#message').val()).done(function () {
                            console.log('Invocation of Send Method in CoreHub succeeded');
                        
                        }).fail(function (error) {
                            console.log('Invocation of CoreHub failed. Error: ' + error);
                        });
                        //hubconn.Send($('#displayname').val(), $('#message').val());
                        // Clear text box and reset focus for next comment.
                        $('#message').val('').focus();
                    });
                });
            });
        
    And the server side looks like this:
     internal void OnTaskStateUpdate(object sender, 
                Pamb.M2olie.ProM2etheus.ProM2etheusCore.OnTaskStateUpdateEventArgs e)
            {
                var context = GlobalHost.ConnectionManager.GetHubContext<CoreHub>();
                context.Clients.All.SendAsync("UpdateTaskState", 
                    e.ProcessInstanceLabel, e.TaskLabel, e.PreviousTaskState, e.CurrentTaskState);
            }
    This method is internally called from an event handler every time the task state changed. The hub method then calls my client method UpdateTaskState. But 
    it doesn_t work. On the client side, nothing happens. What could be the problem? Is it because I do not invoke the server
    method by myself? Is it possible to get updates like this with SignalR without calling a server method from my side first
    or do I only open a channel when I call a server method first? I thought it is enough to say hub.start(). Am I wrong?


    Wednesday, October 14, 2020 10:09 AM

Answers

  • User-1708450884 posted

    Thanks for this hint. I found the error in my code. The server method needed to be implemented like this:

     internal void OnTaskStateUpdate(object sender, 
                MyCore.OnTaskStateUpdateEventArgs e)
            {
                var context = GlobalHost.ConnectionManager.GetHubContext<CoreHub>();
                context.Clients.All.updateTaskState(e.ProcessInstanceLabel, e.TaskLabel, e.PreviousTaskState, e.CurrentTaskState);
                
                //!!!!This call only works with newer versions of SignalR!!!!
                //context.Clients.All.SendAsync("UpdateTaskState", 
                //    e.ProcessInstanceLabel, e.TaskLabel, e.PreviousTaskState, e.CurrentTaskState);
            }

    The async Method only works with later versions of SignalR and Asp.Net, as it seems. 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, October 19, 2020 10:07 AM

All replies

  • User1535942433 posted

    Hi NewbeeSignalR,

    As far as I think,in a SignalR application, the server has no information about the methods that the client implements; when the server invokes a client method, the method name and parameter data are sent to the client, and the method is executed only if it exists in the format that the server specified. If no matching method is found on the client, nothing happens, and no error message is raised on the server.

    I suggest you could turn on logging before the calling the start method on the hub to see what calls are coming from the server.

    More details,you could refer to below article:

    https://docs.microsoft.com/en-us/aspnet/signalr/overview/testing-and-debugging/troubleshooting

    Best regards,

    Yijing Sun

    Thursday, October 15, 2020 5:59 AM
  • User-1708450884 posted

    Thanks for this hint. I found the error in my code. The server method needed to be implemented like this:

     internal void OnTaskStateUpdate(object sender, 
                MyCore.OnTaskStateUpdateEventArgs e)
            {
                var context = GlobalHost.ConnectionManager.GetHubContext<CoreHub>();
                context.Clients.All.updateTaskState(e.ProcessInstanceLabel, e.TaskLabel, e.PreviousTaskState, e.CurrentTaskState);
                
                //!!!!This call only works with newer versions of SignalR!!!!
                //context.Clients.All.SendAsync("UpdateTaskState", 
                //    e.ProcessInstanceLabel, e.TaskLabel, e.PreviousTaskState, e.CurrentTaskState);
            }

    The async Method only works with later versions of SignalR and Asp.Net, as it seems. 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, October 19, 2020 10:07 AM