Base solution for your next web application
Open Closed

Issue with SignalR implementation in our project #11840


User avatar
0
WTPL created

We're utilizing .NET Core 8 in conjunction with jQuery implementation. However, there's an issue where the SignalR hub does not initiate an event when I make a request or access the API endpoint. Please advise on this `SignalR hub not triggering an event when i hit or called endpoint Api ..

Step 1 -- > Created one EventHub (Assembly is --> Wauly.Web.core/Chat/SignalR/EventHub)

using System; using System.Threading.Tasks; using Abp.AspNetCore.SignalR.Hubs; using Abp.Localization; using Abp.RealTime; using Abp.Runtime.Session; using Castle.Core.Logging; using Castle.Windsor; using Microsoft.AspNetCore.SignalR; using wauly.Chat;

namespace wauly.Web.Chat.SignalR { public class EventHub : OnlineClientHubBase { private readonly IChatMessageManager _chatMessageManager; private readonly ILocalizationManager _localizationManager; private readonly IWindsorContainer _windsorContainer; private bool _isCallByRelease; public IAbpSession AbpSession { get; set; }

	public Castle.Core.Logging.ILogger Logger { get; set; }

	public EventHub(
	   IChatMessageManager chatMessageManager,
	   ILocalizationManager localizationManager,
	   IWindsorContainer windsorContainer,
	   IOnlineClientManager<ChatChannel> onlineClientManager,
	   IOnlineClientInfoProvider clientInfoProvider) : base(onlineClientManager, clientInfoProvider)
	{
		_chatMessageManager = chatMessageManager;
		_localizationManager = localizationManager;
		_windsorContainer = windsorContainer;

		Logger = NullLogger.Instance;
		AbpSession = NullAbpSession.Instance;
	}

	public async Task SendMessage(string message)
	{
		await Clients.All.SendAsync("getMessage", string.Format("User {0}: {1}", AbpSession.UserId, message));
	}

	public override async Task OnConnectedAsync()
	{
		await base.OnConnectedAsync();
		Logger.Debug("A client connected to MyChatHub: " + Context.ConnectionId);
	}

	public override async Task OnDisconnectedAsync(Exception exception)
	{
		await base.OnDisconnectedAsync(exception);
		Logger.Debug("A client disconnected from MyChatHub: " + Context.ConnectionId);
	}
}

}

step 2 --> Registered My hub into StartUp file with the existing Hubs.. (Assembly is --> Wauly.Web.Host/Startup/Startup)

app.UseEndpoints(endpoints =>
        {
            endpoints.MapHub<AbpCommonHub>("/signalr");
            endpoints.MapHub<ChatHub>("/signalr-chat");
            endpoints.MapHub<EventHub>("/signalr-eventHub");

			endpoints.MapControllerRoute("defaultWithArea", "{area}/{controller=Home}/{action=Index}/{id?}");
            endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");

            app.ApplicationServices.GetRequiredService<IAbpAspNetCoreConfiguration>().EndpointConfiguration
                .ConfigureAllEndpoints(endpoints);
        });

Step 3 --> Created one service for the API Endpoint (Assembly is --> Wauly.Application/Chat/EventHubAppService)

using System.Threading.Tasks; using Abp.Authorization; using Abp.Domain.Repositories; using Abp.RealTime; using Abp.Runtime.Session; using wauly.Friendships.Cache;

namespace wauly.Chat { [AbpAuthorize] public class EventHubAppService : waulyAppServiceBase, IEventService { private readonly IRepository<ChatMessage, long> _chatMessageRepository; private readonly IUserFriendsCache _userFriendsCache; private readonly IOnlineClientManager

	public EventHubAppService(
		IRepository<ChatMessage, long> chatMessageRepository,
		IUserFriendsCache userFriendsCache,
		IOnlineClientManager<ChatChannel> onlineClientManager,
		IEventCommunicator eventCommunicator)
	{
		_chatMessageRepository = chatMessageRepository;
		_userFriendsCache = userFriendsCache;
		_onlineClientManager = onlineClientManager;
		_eventCommunicator = eventCommunicator;
	}
	public async Task DeviceActivation(long userId,int? tenantId)
	{
		var userIdentifier = AbpSession.ToUserIdentifier();

		var onlineUserClients = await _onlineClientManager.GetAllByUserIdAsync(userIdentifier);
		await _eventCommunicator.DeviceActivation(onlineUserClients, userIdentifier);
	}
}

}

Step 4 --> Created Event Communicator Interface and register there my service (Assembly is --> Wauly.core/Chat/IEventCommunicator)

using System.Collections.Generic; using System.Threading.Tasks; using Abp; using Abp.RealTime;

namespace wauly.Chat { public interface IEventCommunicator { Task DeviceActivation(IReadOnlyList

step 5 -- > After that created Event Communicator and use the DeviceActivation here (Assembly is --> Wauly.Web.core/Chat/SignalR/SignalREventHubCommunicator)

using System.Collections.Generic; using System.Threading.Tasks; using Abp; using Abp.Dependency; using Abp.ObjectMapping; using Abp.RealTime; using Castle.Core.Logging; using Microsoft.AspNetCore.SignalR; using wauly.Chat;

namespace wauly.Web.Chat.SignalR { public class SignalREventHubCommunicator : IEventCommunicator, ITransientDependency { public ILogger Logger { get; set; }

	private readonly IObjectMapper _objectMapper;

	private readonly IHubContext<EventHub> _eventHub;

	public SignalREventHubCommunicator(
		IObjectMapper objectMapper,
		IHubContext<EventHub> eventHub)
	{
		_objectMapper = objectMapper;
		_eventHub = eventHub;
		Logger = NullLogger.Instance;
	}
	public async Task DeviceActivation(IReadOnlyList<IOnlineClient> onlineFriendClients, UserIdentifier user)
	{
		await _eventHub.Clients.All.SendAsync("EventHubActivity","HelloFromApi");
	}
}

}

step 6 --> For the acivation of my eventHub i have writed down acivation logic in index file of device management and also have write other events which are not triggering .. (Assembly is --> Wauly.Web.MVC/WWWroot/View-Resources/Areas/Views/Devices/Index.js)

abp.signalr.startConnection(abp.appPath + 'signalr-eventHub', function (connection) { chatHub = connection; // Save a reference to the hub connection.on('DeviceActivationResponse', function (responseMessage) { console.log('received DeviceActivationResponse: ' + responseMessage);

            // Handle the response here, update UI, etc.
        });
        connection.on('getMessage', function (message) { // Register for incoming messages
            console.log('received message: ' + message);

        });
        connection.on('EventHubActivity', function (message, message1) { // Register for incoming messages
            dataTable.ajax.reload();
            console.log('received message: ' + message + message1);
        });
    }).then(function (connection) {
        abp.log.debug('Connected to EventHub server!');
        abp.event.trigger('myChatHub.connected');


    });

    abp.event.on('myChatHub.connected', function () { // Register for connect event
        chatHub.invoke('sendMessage', "Hi everybody, I'm connected to the Event Hub!"); // Send a message to the server
    });

    // Register for 'EventHubActivity' event
    abp.event.on('EventHubActivity', function (message, message1) {
        console.log('received EventHubActivity message: ' + message + message1);
    });

`


7 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Did you register the Hub as shown below ?

    endpoints.MapHub<EventHub>("/signalr-eventHub");
    
  • User Avatar
    0
    WTPL created

    Hi,

    Certainly, we have implemented the same and also included it in the startup.cs file.

    Thank you. Ajay

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Could you register the hub in Wauly.Web.Mvc/Startup/Startup instead of Wauly.Web.Host/Startup/Startup and see if it works ? As far as we can see, you are using the MVC project.

  • User Avatar
    0
    WTPL created

    Hi we tried that as well , There is no issue of HUB, Connection is getting established , But we are not able to exchange events. We also tried simple code as well `

    using Microsoft.AspNetCore.SignalR;

    public class CommonHub : Hub { public async Task SendEventFromClient(string eventName, string tenantId, string deviceId) { // Process the event on the server -- put this in log with time Console.WriteLine($"Event received from client: {eventName}, TenantId: {tenantId}, DeviceId: {deviceId}");

        // Respond back to the client -- put this in log with time
        await Clients.Caller.SendAsync("ReceiveResponse", $"Server received {eventName} for TenantId: {tenantId}, DeviceId: {deviceId}");
    
       //send event to flutter
        
        await _hubContext.Clients.All.SendAsync("SendEventFromClient", "ENABLE", "tenant123", "device456");
    
    
    }
    

    }

    // Example: Send an event from the client to the server with tenantId and deviceId sendEventToServer("ENABLE", "tenant123", "device456");

    `

  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi, @WTPL

    Step by step, we've accomplished the steps you said. Messaging between clients is taking place. Could you explain the problem you're experiencing in more detail?

  • User Avatar
    0
    WTPL created

    Hi, @oguzhanagir

    To provide context, we are implementing SignalR communication within our "Device Management Module" to facilitate real-time communication with our "Flutter App"." The app, installed on "Windows" or "Android" devices, is intended to communicate with our backend system on various events such as "Device Activation," "Online," "Offline," "Restart," etc.

    The primary role of the SignalR hub is to receive events from the web, specifying both the tenant ID and device ID. Upon detecting any event from the web HUB, the SignalR hub efficiently relays the event to the corresponding Flutter App device.

    I've attached a video recorded by my team that illustrates the problem we're encountering. I believe it's a minor issue that requires your guidance for resolution.

    Video

    Thank you WPTL Team

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    For anyone facing the same issue, here is the solution.

    It seems like it is a bit tricky to connect to SignalR from Postman. You can take a look at articles below;

    1. https://wadehuang36.medium.com/connect-signalr-apis-with-postman-dce2b0f59c2a
    2. https://www.milanjovanovic.tech/blog/adding-real-time-functionality-to-dotnet-applications-with-signalr

    All messages sent to SignalR must end with ASCII character "0x1E.". When you manage to add this ASCII character to the end of each message, all requests will be successfull.