I have a SignalR hub where messages are reaching from client but callback not seems to work.
Server code:
public class ChatHub : Hub<IChatClient>
{
private readonly ILogger<ChatHub> _logger;
public ChatHub(ILogger<ChatHub> logger)
{
_logger = logger;
}
public async Task SendMessage(ChatMessage message)
{
try
{
if (message != null && message.From > 0 && message.To > 0)
{
....
}
await Clients.All.ReceiveMessage(message);
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error in SendMessage {ex.Message}");
}
}
}
Client code for configuring the SignalR:
private void connectChat()
{
_signalRConnection = new HubConnectionBuilder()
.WithUrl(Properties.Settings.Default.APIPath "/hubs/chat").WithAutomaticReconnect()
.Build();
try
{
//Connect to the server
_signalRConnection.StartAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
this.Invoke(new Action(() => txtMessages.AppendText("There was an error opening the connection: " task.Exception.GetBaseException().Message)));
}
else
{
this.Invoke(new Action(() => txtMessages.AppendText("Connected")));
}
});
_signalRConnection.On<string, ChatMessage>("ReceiveMessage", (name, message) =>
{
if (txtMessages.InvokeRequired)
{
txtMessages.Invoke(new Action(() => txtMessages.AppendText($"{name} : {message?.MessageText}" Environment.NewLine)));
}
else
{
txtMessages.AppendText($"{name} : {message?.MessageText}" Environment.NewLine);
}
});
}
catch (Exception)
{
throw;
}
}
Client code for sending message
ChatMessage message = new ChatMessage();
message.MessageText = txtChatMessage.Text;
message.From = UserId.Value;
message.To = toStation;
message.MessageTime = DateTime.Now;
_signalRConnection.SendAsync("SendMessage", message).Wait();
CodePudding user response:
There are a few important details that you need to pay attention to them, for example, make sure:
- You are using the right URL
- The server app is running, before you try to connect
- Start the connection, and wait until the app connects to the hub
- You have correct configurations
- You are using correct callback names for send and receive.
There are two walkthrough docs & learn article which can help you to create a SignalR server and client:
- Step by step article on creating a SignarR server app: Get started with ASP.NET Core SignalR
- Creating the client app, and the error handling, reconnecting, and other related topics: ASP.NET Core SignalR .NET Client.
Windows Forms SignarR client for a ASP.NET Core SignarlR server
Using above mentioned links, here is a very quick step by step example on how to send and receive SignalR messages in a Windows Forms application. In this example, the chat server app is an ASP.NET Core Web application, and the client app is a Windows Forms Application.
Clone or download example
- You can download source
- Or clone the repository: r-aghaei/SignalRExample
Step by step guide
1 - Create the host application
Create an ASP.NET Core Web application, with name
SignalRChat
. (Enable HTTPS, and use .NET 6)Create a folder in the project, with name
Hubs
. And add a new file to it,ChatHub.cs
, with the following content:using Microsoft.AspNetCore.SignalR; namespace SignalRChat.Hubs { public class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } } }
Add SignalR configuration to the Program.cs. Here's the file content after the config added:
using SignalRChat.Hubs; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddSignalR(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.MapHub<ChatHub>("/chatHub"); app.Run();
2 - Create the client application
Create a new WinForms application (.NET 6), with name
SignalRChatClient
.Drop a button, with name
connectButton
Drop a button, with name
sendButton
Drop a textBox, with name
userTextBox
Drop a textBox, with name
messageTextBox
Drop a listBox, with name
messagesList
Double click on
connectButton
to add the empty event handler to the form. We will add the body later.Double click on
sendButton
to add the empty event handler to the form. We will add the body later.Replace the Form1.cs content with the following content: using Microsoft.AspNetCore.SignalR.Client;
namespace SignalRChatClient { public partial class Form1 : Form { HubConnection connection; public Form1() { InitializeComponent(); connection = new HubConnectionBuilder() .WithUrl("https://localhost:7142/ChatHub") .WithAutomaticReconnect() .Build(); } private async void connectButton_Click(object sender, EventArgs e) { connection.On<string, string>("ReceiveMessage", (user, message) => { this.Invoke((Delegate)(() => { var newMessage = $"{user}: {message}"; messagesList.Items.Add(newMessage); })); }); try { await connection.StartAsync(); messagesList.Items.Add("Connection started"); connectButton.Enabled = false; sendButton.Enabled = true; } catch (Exception ex) { messagesList.Items.Add(ex.Message); } } private async void sendButton_Click(object sender, EventArgs e) { try { await connection.InvokeAsync("SendMessage", userTextBox.Text, messageTextBox.Text); } catch (Exception ex) { messagesList.Items.Add(ex.Message); } } } }
Important!: Make sure you modify the URL to the value for your environment. To do so, you can run the web app and see the URL in the browser, or you can open launchSettings.json file and see the URL based on the profile. I'm debugging in VS, so I used the URL
https://localhost:7142
from this node:"profiles": { "SignalRExample": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "https://localhost:7142;http://localhost:5142", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } },
3 - Set multiple Strartup and run
- Right click on the solution and choose Properties
- In the start up projects, choose Multiple Startup Projects and for both SignalRChat and SignalRChatClient choose Start, and save changes.
Now you can press F5 and run the project. Wait until the web browser opens and navigates to the web app. The Windows Form will also open and Form1 will be shown.
Press on Connect button, then after seeing the "Connection started" message in the list, type a username and a message in the text boxes and press Send, and you will receive the message in the list.
There you go!
CodePudding user response:
I think it is because your client method ReceiveMessage
has one parameter:
await Clients.All.ReceiveMessage(message);
While binding event handler you are binding two parameters:
_signalRConnection.On<string, ChatMessage>("ReceiveMessage", (name, message) =>
Correct this to bind right number of parameters.
_signalRConnection.On<ChatMessage>("ReceiveMessage", (message) =>