I’m currently working on a project involving an ASP.NET Core 8 application with SignalR for real-time notifications with SQL Server, an Angular 18 frontend, and SQL Server 2022 Express edition as the database.
I’m experiencing issues with SignalR not sending notifications to the clients after performing CRUD operations on the database.
Here’s a summary of my setup:
Program.cs:
using DocumentApp.Models;
using DocumentApp.Hubs;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddSignalR();
builder.Services.AddControllers();
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAngularApp",
builder => builder
.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());
});
var app = builder.Build();
app.UseCors("AllowAngularApp");
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.MapHub<NotificationHub>("/NotificationHub");
app.Run();
AppDbContext.cs:
using Microsoft.EntityFrameworkCore;
namespace DocumentApp.Models
{
public class AppDbContext : DbContext
{
public DbSet<Document> Documents { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Document>().HasKey(d => d.DocumentId);
}
}
public class Document
{
public int DocumentId { get; set; }
public string DocumentCode { get; set; } = string.Empty;
}
}
NotificationHub.cs:
using Microsoft.AspNetCore.SignalR;
namespace DocumentApp.Hubs
{
public class NotificationHub : Hub
{
// This hub will be used to send notifications to clients
}
}
DocumentsController.cs:
using DocumentApp.Models;
using DocumentApp.Hubs;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace DocumentApp.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class DocumentsController : ControllerBase
{
private readonly AppDbContext _context;
private readonly IHubContext<NotificationHub> _hubContext;
public DocumentsController(AppDbContext context, IHubContext<NotificationHub> hubContext)
{
_context = context;
_hubContext = hubContext;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Document>>> GetDocuments()
{
await _hubContext.Clients.All.SendAsync("ReceiveUpdate", "Documents retrieved!");
return await _context.Documents.ToListAsync();
}
[HttpPost]
public async Task<IActionResult> CreateDocument([FromBody] Document document)
{
_context.Documents.Add(document);
await _context.SaveChangesAsync();
await _hubContext.Clients.All.SendAsync("ReceiveUpdate", $"Document {document.DocumentCode} created!");
return Ok(document);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateDocument(int id, [FromBody] Document document)
{
var existingDocument = await _context.Documents.FindAsync(id);
if (existingDocument == null) return NotFound();
existingDocument.DocumentCode = document.DocumentCode;
await _context.SaveChangesAsync();
await _hubContext.Clients.All.SendAsync("ReceiveUpdate", $"Document {document.DocumentCode} updated!");
return Ok(existingDocument);
}
}
}
Angular 18 frontend:
SignalRService (signalr.service.ts):
import { Injectable } from '@angular/core';
import * as signalR from '@microsoft/signalr';
@Injectable({
providedIn: 'root'
})
export class SignalRService {
private hubConnection: signalR.HubConnection;
constructor() {
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl('https://localhost:7203/NotificationHub')
.configureLogging(signalR.LogLevel.Information)
.build();
this.hubConnection.start()
.then(() => console.log('SignalR connection established'))
.catch(err => console.error('Error establishing connection:', err));
this.hubConnection.on('ReceiveUpdate', (message: string) => {
console.log('Notification received:', message);
});
}
}
SQL Server - database configuration:
ALTER DATABASE DMS_DB_1_0_0
SET ENABLE_BROKER;
GO
SQL Server Agent: enabled the SQL Server Agent.
Problem
Despite performing CRUD operations (create, update, delete) through the API, the SignalR notifications are not being received in the Angular client. I've tried connecting directly to the /NotificationHub endpoint via Postman, which connects but doesn't receive any notifications.
Console error: when accessing https://localhost:7203/NotificationHub directly in the browser, I receive a "Connection ID required" error.
Steps taken to diagnose:
- Verified that the SignalR Hub is correctly mapped in
Program.cs. - Checked that the SignalR client in Angular is properly configured.
- Ensured that CORS is correctly set up to allow connections from the Angular app.
- Tried testing WebSocket connections with Postman, which connects but doesn't receive notifications.
Question
What steps should I take to resolve this issue? How can I ensure that SignalR notifications are properly sent and received by the Angular client? Are there any additional configurations or debugging techniques I should try?
Thank you in advance for your help!