I try to get a very basic SignalR example to work that is based on Microsoft’s tutorial and the Weatherforecast .NET/Angular SPA created by Visual Studio as a basis as this is the same type of project I later want to use SignalR with. The entire source code is at GitHub.
It looks as if the handshake/negotiation works and a websocket connection is established – but no messages are flowing there. This is what the Chrome Developer Tools show:
I have the feeling I overlooked something minor, but I’m struggling to see what it could be.
I started by adjusting the Program.cs
file, this is the relevant code:
builder.Services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
});
var app = builder.Build();
...
app.UseCors();
//app.MapHub<ProgressHub>("/progressHub");
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ProgressHub>("/progresshub"); // Map the hub URL here
});
app.Run();
Note that MS suggests to use app.MapHub<ProgressHub>("/progressHub");
but som resources suggested to use app.UseEndpoints
instead. It doesn’t seem to make any difference. Also, I tried using app.UseWebSockets();
but that did not change anything either. Also, I made sure to enable CORS.
This is the controller method I added which is supposed to send messages on the SignalR channel:
[HttpPost("startProcess")]
public async Task<IActionResult> StartProcess()
{
// Some logic to start the long-running process
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
// Report progress to the client
await _hubContext.Clients.All.SendAsync("ReceiveProgressUpdate", $"Step {i + 1} completed.");
}
return Ok("[]");
}
When stepping through the code, no exceptions are thrown, the code runs without any issues. On the Angular client side I have installed the signalr package and created a service:
export class SignalRService {
private hubConnection: HubConnection;
private progressSubject: Subject<string> = new Subject<string>();
constructor() {
this.hubConnection = new HubConnectionBuilder()
.withUrl('https://localhost:44429/progresshub')
.build();
this.hubConnection.on('ReceiveProgressUpdate', (progressMessage: string) => {
this.progressSubject.next(progressMessage);
});
this.hubConnection.start().catch(err => console.error(err));
}
getProgressUpdates() {
return this.progressSubject.asObservable();
}
}
Now I use that service in my SignalR component, but the progressUpdates array remains empty:
export class SignalRComponent implements OnInit {
progressUpdates: string[] = [];
_httpClient: HttpClient;
constructor(private httpClient: HttpClient, private signalRService: SignalRService) {
this._httpClient = httpClient;
}
ngOnInit() {
this.signalRService.getProgressUpdates().subscribe((progressMessage: string) => {
this.progressUpdates.push(progressMessage);
});
}
startProcess() {
this.httpClient.post('https://localhost:44429/weatherforecast/startProcess', {}).subscribe();
}
}
Also, I have turned on the WebSocket Protocol in Windows as this was suggested on SO as well:
2
Answers
I finally found the culprit, it is the ASP proxy which per default configuration does not allow websocket connections. The
PROXY_CONFIG
const inproxy.conf.js
needs to be set like this:The configuration needs to be split into separate contexts for the weatherforecast (or any other) API and the websocket as the Keep-Alive headers are not allowed for websocket connections.
Credit goes to this post on reddit.
I download your repo and change the
proxy.conf.js
file like below. And it works well. You can according your needs to change other settings.I also enable the client side logging so that we can make the connection is established.
Test Result
proxy.conf.js
signal-r.service.ts