Angular SignalR hub proxy experiencing malfunction

I'm trying to integrate SignalR into my Angular MVC application. I started with this article which provides a hub proxy factory to facilitate hub calls between the server and Angular code. Despite setting everything up, the communication between my server hub and Angular code is not functioning properly. Here's the code snippet:

Hub proxy factory:

app.factory('hubProxy', ['$rootScope', 'signalRUrl', function ($rootScope, signalRUrl) {

    function hubFactory(hubName) {
        var connection = $.hubConnection(signalRUrl);
        var proxy = connection.createHubProxy(hubName);

        connection.start().done(function () { });

        return {
            on: function (eventName, callback) {
                proxy.on(eventName, function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            invoke: function (methodName, callback) {
                proxy.invoke(methodName)
                .done(function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            connection: connection
        };
    };

    return hubFactory;
}]);

Angular controller:

angular.module('testApp').controller('testController', ['$scope', 'hubProxy', function ($scope, hubProxy) {
    var pendingPaymentsHub = hubProxy('pendingPaymentsHub');

    pendingPaymentsHub.on('onUpdatePendingPayment', function (data) {
        console.log('hub callback!');
    });
}]);

Hub:

[HubName("pendingPaymentsHub")]
public class PendingPaymentsHub : Hub
{
    private static IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<PendingPaymentsHub>();

    public static void UpdatePendingPayment(PendingPaymentViewModel pendingPayment)
    {
        hub.Clients.All.onUpdatePendingPayment(pendingPayment);
    }
}

The hub is called from an API controller post-update. It is triggered like this:

PendingPaymentsHub.UpdatePendingPayment(pendingPayment);

Upon page load, both /signalr/negotiate and /signalr/start requests run successfully (200 status confirmed in browser dev tools). In addition, I've verified that the UpdatePendingPayment method in the hub is being executed during debugging. However, there is no activity happening on the front-end. What could be causing this?

Thank you for your assistance.

Update: The issue lies within the hub proxy factory implementation. If I replace it with the following code snippet in my controller, everything works as intended:

function initializeHub() {
    connection = $.hubConnection(signalRUrl);
    hub = connection.createHubProxy('pendingPaymentsHub');

    hub.on('onUpdatePendingPayment', function (data) {
        console.log('success');
    });

    connection.start();
};

Answer №1

Consider using uppercase letters when making server-side method calls to the client, even if they are lowercase on the client side:

hub.Clients.All.OnUpdatePendingPayment(pendingPayment);

Review the generated proxy to determine how methods are mapped. This is where I discovered the issue with uppercase letters.

The excerpt Misspelled method, incorrect method signature, or incorrect hub name addresses this issue, as the proxy uses camelCase:

[...] Also, SignalR creates the hub proxy using camel-cased methods, as is appropriate in JavaScript, so a method called SendMessage on the server would be called sendMessage in the client proxy.

Answer №2

While following the same tutorial, I encountered a small issue that required me to make a minor adjustment in order for everything to work properly. The key was ensuring that the connection.start() method was called after defining the .on() method for the hubProxy object. It's still a mystery to me how the tutorial example managed to function correctly without this step.

Take a look at my revised service implementation below:

app.factory('hubProxy', ['$rootScope', 'serverUrl', function ($rootScope, serverUrl) {

    function backendFactory(hubName) {
        $.support.cors = true;
        var connection = $.hubConnection(serverUrl);
        var proxy = connection.createHubProxy(hubName);

        return {

            on: function (eventName, callback) {
                proxy.on(eventName, function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            invoke: function (methodName, callback) {
                proxy.invoke(methodName)
                .done(function (result) {
                    $rootScope.$apply(function () {
                        if (callback) {
                            callback(result);
                        }
                    });
                });
            },
            start: function(){
                connection.start().done(function () { });
            }
        };
    };

    return backendFactory;
}]);

Remember to call the start() method after the on() method as shown here:

app.controller('hubDataController', ['$scope', 'hubProxy',
    function ($scope, hubProxy) {

    var proxy = hubProxy('remoteHub');        

    proxy.on('broadcast', function (data) {
        console.log(data);
    });

    proxy.start();
}

]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to prevent a THREE.js raycast from intersecting with HTML elements?

Is there a way to make HTML elements block THREE.js raycasts on my webpage? I want the DIV element to prevent the raycast from retrieving objects in my scene when it is open and the user clicks on it. Rather than disabling raycasting completely, I just wan ...

Retrieve records with at least one connection, but display all of them

After creating this entry, it now consists of 2 tags - tag1 and tag2. { "id": "d87de1d9-b048-4867-92fb-a84dca59c87e", "name": "Test Name", "tags": [ { "id": "fa0ca8fd-eff4-4e58-8bb0-a1ef726f01d4", "name": "tag1", "organizationI ...

Fresh to Angular: Understanding Calculated Variables

Transitioning from Knockout to Angular has presented me with a few challenges. It seems like I might be approaching things in a non-angular manner. http://jsfiddle.net/LostInDaJungle/BxELP/ I've provided the link to jsfiddle instead of including my ...

How can I make a button click itself automatically?

When a user clicks a button, the other button should automatically click itself to display an inspirational quote. Upon clicking a button on the webpage, a quote will be displayed without requiring the user to click both buttons. Efforts have been made to ...

The AJAX request is lacking a proper reference to the variable

This is the code I am working with: $('.store-card').each(function() { placeid = $(this).data('placeid'); latlng = $(this).data('latlng'); card = this; console.log("1 ", card); $.ajax({ url: '/stores/pl ...

What is the best way to create a random key using a factory function?

I am working on a function that generates objects, and I would like to be able to specify the key for the object as a parameter. However, when I try to do this, the function does not recognize the parameter properly and sets its name as the key instead. h ...

An issue occurred in React 16.14.0 where the error "ReferenceError: exports is not defined" was not properly

As the creator of the next-translate library, I have encountered a perplexing issue with an experimental version involving an error specifically related to React 16.14.0. Interestingly, upgrading React to version 17 resolves the issue, but I am hesitant to ...

Store a fictional boolean value in state and distribute it among components

Is there a way to share state across components in React? I want a user to be able to click on an ArtImage, which will render a div. When this happens, the value of selected should be added to the selected images state and display the total number of selec ...

Having trouble with implementing the .addclass function in a dice roller project

I'm looking to have the element with id=die load initially, and then on a button click event labeled "click me," apply the corresponding CSS class such as 'die1,' 'die2,' and so forth. function roll() { var die = Math.floor(Ma ...

The slideToggle() function appears to be malfunctioning when sliding up or down, as it

Currently, I am in the process of creating a dropdown menu. However, I am facing an issue where the menu does not slide down or up smoothly when clicked. The animations seem to be delayed or non-existent. $('.menu-vertical .nav-menu > li'). ...

What is the best way to retrieve a specific value from an array of objects based on a condition?

I need some assistance with writing a function. Can you help me out? Let's say I have an array of objects: const movieGen = [ { id: 28, name: "Action" }, { id: 12, name: "Adventure" }, { id: 16, name: "Animation" }, ...

When adding a new row of information to a table during an e2e test on Cypress, I am encountering difficulty retrieving the data from the most recent row

Using Cypress for e2e testing in an application, the specific behavior being tested involves: Entering information into a form. Submitting the form. Expecting a new field to be created and placed at the bottom of a table. Checking that the last field cont ...

Utilizing npm packages from third-party sources within a custom extension for personal use (not intended for distribution)

Exploring the idea of developing a basic Firefox extension that involves external modules such as Firebase and Cheerio, but there doesn't seem to be much information available on this topic. I noticed there are legacy options like jpm, but they'r ...

Is it possible for files not to load when in the main directory?

I encountered a strange issue with my file structure. After setting up the server and trying to run it, I found that the index.html wouldn't load unless placed in a folder. The browser displayed "Cannot GET /". The same problem occurred with my JS fil ...

Ways to determine if the mouse is positioned at the bottom of a div area

I have multiple sections and I am trying to change the mouse cursor when it is within 200px of the bottom of each section. Although I used the code provided, it only seems to work for the first section. The e.pageY value is not being reset in subsequent s ...

Is there a way to export a specific portion of a destructuring assignment?

const { a, ...rest } = { a: 1, b: 2, c: 3 }; If I want to export only the rest object in TypeScript, how can I achieve that? ...

Dynamically update a form with steps using JQuery-steps and send all objects to the controller

In the context of a form, it is possible to dynamically add between 1 to n records before passing it to the controller with data. The following represents the ViewModel for the form: public class AddFieldDataViewModel { public int SampleID { get; se ...

"Vue's watch method seems to be failing to properly filter through

The filter functionality within a Vue watched function doesn't appear to be functioning as expected. Despite returning false for the E: object and true for all other items, the E: object remains in the array when it should have been removed. Below is ...

Using JavaScript to show a prompt message inside an h1 tag within a newly created div

I have developed a basic JavaScript program that opens a prompt dialog when the div tag is clicked, allowing the user to enter text. The program then creates a new div element and displays the entered text above it. However, I am facing an issue where I wa ...

What is the best way to navigate to a different page, such as Google, using Node.js?

I need to retrieve a number to store in a short variable, and then search the database for a corresponding shortUrl associated with that number. If a match is found, I want the response to be the full URL, such as www.google.com. For example, if a user ty ...