寻求基于SignalR的.NET用户间推送通知方案及示例
Hey there! SignalR is exactly the right tool for this scenario—you can get instant, real-time notifications without relying on slow database polling. Let’s break down a complete, workable approach with .NET-specific examples to get you up and running.
Core Approach
Instead of writing to a database and repeatedly checking for changes, we’ll trigger SignalR notifications the moment a user inserts a new table row. This keeps things fast and lightweight. Here’s the simple flow:
- A user submits a new table row to your backend.
- Your backend processes the row (save it to memory, a file, or a database—we just skip polling).
- Your backend uses SignalR to push an update to all other connected users immediately.
- Clients receive the notification and refresh their table view automatically.
Step 1: Set Up the SignalR Hub
First, create a SignalR Hub class—this acts as the central communication bridge between your server and clients.
using Microsoft.AspNetCore.SignalR; public class TableUpdatesHub : Hub { // We'll use server-side triggers to call this, but it can also be invoked from clients public async Task SendTableUpdate(string rowData) { // Send the update to every connected client except the one who triggered it await Clients.Others.SendAsync("ReceiveTableUpdate", rowData); } }
Next, register SignalR in your Program.cs to enable the service and map the hub to a route:
var builder = WebApplication.CreateBuilder(args); // Add SignalR to your service collection builder.Services.AddSignalR(); // ... other service registrations (controllers, Razor Pages, etc.) var app = builder.Build(); // ... middleware setup (static files, authentication, etc.) // Map the hub to a URL clients can connect to app.MapHub<TableUpdatesHub>("/tableUpdatesHub"); app.Run();
Step 2: Trigger Notifications from the Backend
When a user inserts a new row, inject IHubContext<TableUpdatesHub> into your controller/service to send the real-time update to other users.
Example: Controller Action for Adding Rows
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; [ApiController] [Route("api/table")] public class TableController : ControllerBase { private readonly IHubContext<TableUpdatesHub> _hubContext; // Use a service to manage your table data (in-memory or persistent—no polling needed!) private readonly ITableDataService _tableDataService; public TableController(IHubContext<TableUpdatesHub> hubContext, ITableDataService tableDataService) { _hubContext = hubContext; _tableDataService = tableDataService; } [HttpPost("rows")] public async Task<IActionResult> AddRow([FromBody] TableRow newRow) { // 1. Save the new row to your data store await _tableDataService.AddRowAsync(newRow); // 2. Serialize the row data to send to clients var rowJson = System.Text.Json.JsonSerializer.Serialize(newRow); // 3. Notify all other connected users about the new row await _hubContext.Clients.Others.SendAsync("ReceiveTableUpdate", rowJson); return Ok(newRow); } } // DTO for your table row public class TableRow { public int Id { get; set; } public string Column1 { get; set; } = string.Empty; public string Column2 { get; set; } = string.Empty; }
Step 3: Client-Side Integration
Connect your frontend to the SignalR hub to receive and display updates. Below are examples for two common .NET frontend scenarios:
Option 1: Blazor (Server or WebAssembly)
In a Blazor component (e.g., SharedTable.razor):
@page "/shared-table" @inject HubConnection HubConnection @inject HttpClient Http @implements IAsyncDisposable <h3>Shared Table</h3> <table class="table"> <thead> <tr> <th>ID</th> <th>Column 1</th> <th>Column 2</th> </tr> </thead> <tbody> @foreach (var row in TableRows) { <tr> <td>@row.Id</td> <td>@row.Column1</td> <td>@row.Column2</td> </tr> } </tbody> </table> @code { private List<TableRow> TableRows = new(); protected override async Task OnInitializedAsync() { // Initialize the hub connection HubConnection = new HubConnectionBuilder() .WithUrl(NavigationManager.ToAbsoluteUri("/tableUpdatesHub")) .Build(); // Listen for incoming table updates HubConnection.On<string>("ReceiveTableUpdate", async (rowJson) => { var newRow = System.Text.Json.JsonSerializer.Deserialize<TableRow>(rowJson); if (newRow != null) { TableRows.Add(newRow); StateHasChanged(); // Refresh the UI } }); await HubConnection.StartAsync(); // Load initial table data from your API TableRows = await Http.GetFromJsonAsync<List<TableRow>>("/api/table/rows") ?? new(); } public async ValueTask DisposeAsync() { if (HubConnection != null) { await HubConnection.DisposeAsync(); } } }
Don’t forget to register the HubConnection in Program.cs for Blazor:
builder.Services.AddScoped<HubConnection>(sp => { var navigationManager = sp.GetRequiredService<NavigationManager>(); return new HubConnectionBuilder() .WithUrl(navigationManager.ToAbsoluteUri("/tableUpdatesHub")) .Build(); });
Option 2: Razor Pages/MVC (JavaScript)
In your Razor Page or View, add this JavaScript to connect to the hub and update the table:
<script src="~/lib/signalr/dist/browser/signalr.js"></script> <script> // Initialize the SignalR connection const connection = new signalR.HubConnectionBuilder() .withUrl("/tableUpdatesHub") .build(); // Listen for new row updates connection.on("ReceiveTableUpdate", function (rowJson) { const newRow = JSON.parse(rowJson); // Add the new row to the table DOM const tableBody = document.getElementById("table-body"); const rowElement = document.createElement("tr"); rowElement.innerHTML = ` <td>${newRow.id}</td> <td>${newRow.column1}</td> <td>${newRow.column2}</td> `; tableBody.appendChild(rowElement); }); // Start the connection connection.start().catch(function (err) { return console.error(err.toString()); }); </script> <table class="table"> <thead> <tr> <th>ID</th> <th>Column 1</th> <th>Column 2</th> </tr> </thead> <tbody id="table-body"> <!-- Initial rows loaded from server --> </tbody> </table>
Key Notes
- No Database Polling: We push updates directly from the server when a row is inserted—no repeated database checks to slow things down.
- Targeted Notifications:
Clients.Othersensures the user who added the row doesn’t get a duplicate update (useClients.Allif you want everyone, including the sender, to see the update). - Scalability: If you need to scale beyond a single server, add a SignalR backplane (like Redis or Azure Service Bus) to sync messages across servers. For small to medium apps, the basic setup works perfectly.
内容的提问来源于stack exchange,提问作者Alexandra Damaschin

