Search code examples
react-native.net-coreexposignalr

SignalR with React Native Expo:: NOTHING is happening


I have a mobile app with messaging functionality. The backend is a .NET Core 6.0 console application. The front end is a React Native Expo application. When a user hits the "send" button, it saves the message in the database and pushes the new message to the other user's screen (currently it's only one to one conversation). Everything works except when it's trying to push the new message to the recipient. I have tried other solutions on Stackoverflow but none so far has been helpful...

The .NET application is hosted on Azure and I am using the actual device to run the Expo app.

The new message is not pushed to the recipient's screen. I was getting some 404 errors before but turned out to be something else. I walked through the code and it executed the _messageHub.Clients.All.SendAsync("ReceivedMessage", message); fine but the other phone is not getting the new message.

React Native Expo code:

import { HubConnectionBuilder } from '@microsoft/signalr';
import React, { useEffect, useState } from 'react';

export default function Conversation({ navigation, route }: any) {
    const [messages, setMessages] = useState([]);
    const [message, setMessage] = useState("");
    const conversation = route.params.data;
    const personId = getCurrentUser().personId;

    useEffect(() => {
        loadMessages();

        try {
            const connection = new HubConnectionBuilder()
                .withUrl(`${Settings.ApiUrl}/hubs-message`)
                .build();
            connection.start().then(() => console.log("started"));
            connection.on("ReceivedMessage", message => {
                console.log(message);
                let updateMessage = messages;
                updateMessage.unshift(message);
                setMessages(updateMessage);
            });
        }
        catch (e) { console.error("error here", e); }
    }, []);

    const sendMessage = () => {
        postUser(`${Settings.ApiUrl}/v1/Message/Send`, {
            message: message,
            conversationId: conversation.id
        }).then((data: any) => {
            setMessage("");
            let updateMessages = [...messages];
            updateMessages.unshift(data.Message);
            setMessages(updateMessages);
        });
    };
....
....
}

.NET Core code:

Program.cs

builder.Services.AddSignalR();
var app = builder.Build();
...
...
app.UseCors();
app.UseHttpsRedirection();
app.MapControllers();
app.UseAuthentication();
app.UseAuthorization();
app.MapHub<MessageHub>("/hubs-message");

MessageHub.cs //does not have much at the moment...

[Authorize]
public class MessageHub : Hub
{
    
}

NotificationService.cs //this is called by the MessageController after saving the message to the database to push the new message to the recipient.

public class NotificationService
{
    private readonly IHubContext<MessageHub> _messageHub;
    public NotificationService(IHubContext<MessageHub> messageHub) 
    { 
        _messageHub = messageHub;
    }
    ...
    ...
    if (newMessageSentData.ActiveOnConversationId == conversationId)
    {
        try
        {
           //push new message to receiver
           _messageHub.Clients.All.SendAsync("ReceivedMessage", message);
        }
        catch (Exception ex)
        {
           //NO exception thrown
           var a = ex.Message;
        }
    }
}

Solution

  • I was able to get it to work by moving to Azure SignalR. It's quite easy to set up. Here is a youtube video showing to to do that https://www.youtube.com/watch?v=wpQZrQ6Wnbw&t=759s.

    Azure portal

    Add the SignalR service to my resource group and copy the connection string under the Settings group

    program.cs,

    builder.Services.AddSignalR().AddAzureSignalR("[Azure SignalR Connection String]");
    var app = builder.Build();
    ...
    ...
    app.UseAzureSignalR(routes =>
    {
        routes.MapHub<MessageHub>("/hubs-message");
    });