SignalR 2.2 users are experiencing a lack of message reception

I have developed a unique self-hosted SignalR application that is operating within the framework of a console application. To access the hubs within this application, I have implemented a wrapper class to avoid referencing the SignalR.Core assemblies directly in my ASP.NET project. This way, another C# class within my application is responsible for transmitting messages to connected clients.

Although I am able to interact with the PlanHub methods (Register and Unregister) directly from Javascript and reach breakpoints successfully, I encounter an issue when attempting to call client methods from a different class outside of the Hub. Even when using Clients.All to rule out concerns with Group registration, the message does not reach the intended clients. What could be causing this problem?

Upon examining the code, it appears that the line

Clients.All.updateStatus(planId, message);
is executed without errors, but no data is displayed on the client's console log.

Here are the key sections of the code:

PlanHub.cs

public class PlanHub : Hub
{
    private const string GroupPrefix = "PlanGroup_";

    public void Register(int companyId)
    {
        Groups.Add(Context.ConnectionId, $"{GroupPrefix}{companyId}");
    }

    public void Unregister(int companyId)
    {
        Groups.Remove(Context.ConnectionId, $"{GroupPrefix}{companyId}");
    }
}

PlanPublisher.cs

public class PlanPublisher
{
    private readonly static Lazy<PlanPublisher> _instance = new Lazy<PlanPublisher>(() => 
        new PlanPublisher(GlobalHost.ConnectionManager.GetHubContext<PlanHub>().Clients));
    private IHubConnectionContext<dynamic> Clients { get; set; }

    private PlanPublisher(IHubConnectionContext<dynamic> clients)
    {
        Clients = clients;
    }

    public static PlanPublisher Instance => _instance.Value;

    public void UpdateStatus(int planId, string message)
    {
        //Despite no exceptions being thrown, the message is not received by clients.
        //Even testing with Clients.All instead of Groups did not resolve the issue.
        Clients.All.updateStatus(planId, message);
    }
}

Calling code (from within another C# class)

PlanPublisher.Instance.UpdateStatus(plan.Id, $"Publishing started for {plan.Name}...");

Javascript

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> 
<script src="~/scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="http://localhost:8080/signalr/hubs"></script>
<script>
    $(document).ready(function() {
        $.connection.hub.url = "http://localhost:8080/signalr";

        var planMessagePublisher = $.connection.planHub;

        planMessagePublisher.client.updateStatus = function (planId, message) {
            console.log('Status: ' + planId + ' - ' + message);
        };

        $.connection.hub.start().done(function() {
            //The PlanHub.Register method executes successfully at this point.
            planMessagePublisher.server.register(@Model.CompanyId);

            // Also successfully logs the new connection ID to the console
            console.log('Now connected, connection ID=' + $.connection.hub.id);
        });
    });
</script>

JS Console Debugger Output

jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Auto detected cross domain url.
jquery.signalR-2.2.0.min.js?v=8588299:8 [06:23:19 GMT-0700 (Pacific Daylight Time)] SignalR: Client subscribed to hub 'planhub'.
...

Despite correct registration, the expected data does not propagate to the clients. The line

Clients.All.updateStatus(planId, message);
gets triggered multiple times, yet the additional logging data never reaches the console as anticipated.

UPDATE: Inquiring about a potential custom dependency resolver, the presented code resides isolated within its own project with minimal external components besides what has been showcased here. Although the section calling PlanPublisher.UpdateStatus() does feature a custom dependency resolver, this should not affect operations since it is segregated within its distinct assembly. Both PlanPublisher.cs and PlanHub.cs exist within a simplistic project solely linked to SignalR.Core and SignalR.SelfHost.

Answer №1

I attempted to simplify the example you provided (using SignalR 2.2.0)

Below is the Hub class:

public class PlanHub : Hub
{
    private const string GroupPrefix = "PlanGroup_";

    // hubcontext
    private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext <PlanHub> ();

    public void Register(int companyId)
    {
        Groups.Add(Context.ConnectionId, $"{GroupPrefix}{companyId}");
    }

    public void Unregister(int companyId)
    {
        Groups.Remove(Context.ConnectionId, $"{GroupPrefix}{companyId}");
    }

    // static method using hub context
    public static void Static_UpdateStatus(int planId, string message)
    {
        hubContext.Clients.All.updateStatus(planId, message);
    }
}

As I do not have a backend and I am unsure about your approach, I set up a timer to call the method from C# every 10 seconds.

Code for calling and dummy timer:

    public void startTimer()
    {
        timer = new System.Timers.Timer();
        timer.Elapsed += new System.Timers.ElapsedEventHandler(ExecuteTimerJob);
        timer.Interval = 10000; // 10 sec
        timer.Start();
    }

    public static void ExecuteTimerJob(object source, System.Timers.ElapsedEventArgs e)
    {
        // this is the call from C#
        PlanHub.Static_UpdateStatus(123, "some message");
    }

Javascript code snippet:

$(function () {
    var planHub = $.connection.planHub;
    $.connection.hub.start().done(function () {
         console.debug('Connected to PlanHub...');
    })
    planHub.client.updateStatus = function (planId, message) {
        console.log("planId: " + planId);
        console.log("message: " + message);
    } 
});

Check the browser console for the result:

https://i.sstatic.net/AUmCc.png

Answer №2

Give this a shot:

public void UpdateStatus(int id, string msg)
{
    var users = GlobalHost.ConnectionManager.GetHubContext<PlanHub>().Clients;
    users.All.updateStats(id, msg);
}

It seems that the issue lies in initializing PlanPublisher before the hub context (and Clients) are fully created.

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

How to upload a document to Alfresco using JavaScript API

I am facing an issue while attempting to upload a file from a node application to my local Alfresco server. I have been able to login, create, and delete folders successfully, but I am encountering difficulties when trying to upload files. let AlfrescoApi ...

The Material UI Drawer is fading into the background instead of smoothly sliding into view

Seeking guidance as a novice in SD, I am dedicating my free time to honing my skills. Any advice is appreciated, but please explain it as if I were a child. My current endeavor involves making the Drawer Component feature functional and customizing it to s ...

Personalized HTML selection list

When a select option is too long, it stretches the container to accommodate its length. I have created a truncate function to limit the display to 20 characters and add ellipses to prevent this stretching. I have been searching for a way to show the entir ...

Creating a consolidated ImageSource from a WPF DrawingGroup

My current approach involves using a System.Windows.Media.DrawingGroup to store multiple tiled images (ImageDrawing) within the Children-DrawingCollection property. However, this method tends to slow down significantly when displaying the entire DrawingGro ...

Executing a personalized function within a Server Component with the Next JS App Router while the application is running

In my server component Home, I call the function getMyAge: // app/page.tsx import { getMyAge } from './utils/datetime'; export default function Home() { return ( <Page> <Paragraph>I'm {getMyAge()} years old</Parag ...

What is the best way to show the current value of a checkbox element in the future?

I want to add multiple checkboxes using this method: $(".btn-sample").on("click", function() { $(".container").append( '<input class="check-sample" type="checkbox" value="'+check_value+'"/>' ); }); The issue I' ...

Encountering issues when attempting to insert information into PostgreSql utilizing AngularJs paired with a C# WebService backend

As a beginner in angularjs, I have set up the HTML file and linked it to the RegistrationController.js. Additionally, I have created the Registration.cs file for managing data retrieval and storage from a database. Despite not encountering any errors, I am ...

Encountering difficulties in compiling Dynamic HTML with the $compile function

I'm attempting to incorporate dynamic HTML into my code with the following lines: var el = $compile('<a ng-controller=\"tableController\" ng-click=\"open\">...ReadMore</a>')($scope); But I'm encounterin ...

Tips on removing properties from an object recursively according to their key/value pairs

My current task involves removing specific children of an object based on whether their "size" key is set to 0. To achieve this, I am utilizing the npm package directory-tree to generate a JavaScript object representation of a chosen directory. The stru ...

Transform current JSON data into formatted JSON format using JavaScript or TypeScript

I have a JSON structure that needs to be reformatted in order to meet the requirements of an external service. Although the current format is complex and cannot be altered, I need to modify it to match the desired output for the external service. Current ...

Implement a feature in JS/HTML where clicking on a button shifts a specific section of a row from one table to another while simultaneously deleting the remaining

I am facing an issue with two tables - addFriends and existingFriends. The addFriends table contains a button in the fourth column, which, upon clicking, should delete the corresponding row from that table and add it to the existingFriends table. Currentl ...

Constructing a JSON schema for a dynamic aggregate query

Looking to create a query that matches fields with data in them. Here is an attempt: var matchStr = {}; if (received.user) { matchStr = { "_id": { "$regex": received.user, "$options": "i" } }; } if (received.name) { matchStr += { "name": { " ...

Utilizing .html() to convert JSON data into HTML content

I have thoroughly commented the code below in my attempt to retrieve JSON data and pass it to the 'results' div in my HTML view. However, this process seems to return nothing, making it challenging to debug since no output can be displayed on the ...

The process of making a pop-up modal instead of just relying on alerts

Attempting to change from using an alert to a pop-up with a simple if statement, but encountering some issues. Here is the current code: if(values == ''){ $('body').css('cursor','auto'); alert("Blah Blah..." ...

The 'ObjectID' property is not present in the 'CollectionStatic' data type

Encountering an issue with the MongoDB npm module: mongoId = new Mongo.Collection.ObjectID()._str; Attached is a screenshot for reference. Appreciate any assistance.https://i.sstatic.net/EHdMo.png ...

Resuming the programming process on a separate thread

Currently, I am working on creating code that is executed on the UI thread, then calls some code on a separate thread (not from ThreadPool, but consistently the same thread), and finally resumes back on the UI thread. I am seeking advice on the most effici ...

implementation of an Ajax countdown timer on an ASP.NET webpage

My website has a timeout of 5 minutes. I want to display the countdown in minutes and seconds, like this: 4 minutes and 10 seconds remaining I attempted to use the code below to accomplish this: <asp:Timer ID="Timer1" runat="server" ...

Hide button for the last input form to dynamically remove in jQuery

At first, I hide the remove button when there is only one form. However, if there are multiple forms and the user deletes all of them, I want the last form to remain visible and not be deleted. Can someone assist with this issue? Here is my code: <! ...

`The console is displaying incorrect results when returning a JSON object`

Need to extract the full address as well as the lat and long values from the provided JSON data. var place = { "address_components": [{ "long_name": "17", "short_name": "17", "types": [ "street_number" ] }, ... ...

Tips for troubleshooting and resolving the npm ERR! code E404 issue in Vue.js when implementing a datepicker

I am a newcomer to Vue.js and I am currently exploring the use of a datepicker from However, upon importing the script for usage, I encountered the following message: 'VMdDateRangePicker' is declared but its value is never read.ts(6133) Cou ...