Blazor订阅通知服务后UI不实时更新的问题排查
问题分析与解决方案
你的核心问题在于客户端的ClientNotificationService从未触发OnChange事件,同时API控制器的参数绑定存在错误,导致通知流程不完整。以下是具体修复步骤:
一、修复客户端通知服务(ClientNotificationService)
客户端发送/删除通知后,需要主动触发OnChange事件,通知UI更新:
public class ClientNotificationService(HttpClient httpClient) : INotificationService { private readonly HttpClient _httpClient = httpClient; public event Action? OnChange; public async Task SendNotification(string message, NotificationType messageType) { Notification notification = new Notification { message = message, messageType = messageType }; var response = await _httpClient.PostAsJsonAsync("api/Notification", notification); if (!response.IsSuccessStatusCode) { throw new Exception($"Failed to send notification. Status code: {response.StatusCode}"); } // 发送成功后触发事件,通知UI刷新 OnChange?.Invoke(); } public async Task<List<Notification>> GetNotifications() { // 避免返回null,默认返回空列表 var response = await _httpClient.GetFromJsonAsync<List<Notification>>("api/Notification"); return response ?? new List<Notification>(); } public async Task RemoveOldestNotification() { // 替换.Result为await,避免同步阻塞 var response = await _httpClient.DeleteAsync("api/Notification"); if (!response.IsSuccessStatusCode) { throw new Exception($"Failed to remove notification. Status code: {response.StatusCode}"); } // 删除成功后触发事件 OnChange?.Invoke(); } }
二、修复API控制器参数绑定
客户端发送的是Notification对象,但原控制器方法接收的是两个单独参数,导致参数绑定失败。修改NotificationController的SendNotification方法:
[Route("api/[controller]")] [ApiController] public class NotificationController(INotificationService notificationService) : ControllerBase { [HttpGet] public async Task<ActionResult> GetNotifications() { var notifications = await notificationService.GetNotifications(); return Ok(notifications); } // 接收FromBody的Notification对象 [HttpPost] public async Task<ActionResult> SendNotification([FromBody] Notification notification) { if (notification == null || string.IsNullOrWhiteSpace(notification.message)) { return BadRequest("Invalid notification content"); } await notificationService.SendNotification(notification.message, notification.messageType); return Ok(); } [HttpDelete] public async Task<ActionResult> RemoveOldestNotification() { await notificationService.RemoveOldestNotification(); return Ok(); } }
三、确保服务端通知服务是单例
服务端的NotificationService必须注册为单例,否则每次API请求都会创建新实例,导致通知列表无法共享:
在服务端Program.cs中添加:
builder.Services.AddSingleton<INotificationService, NotificationService>();
客户端Program.cs注册客户端服务:
builder.Services.AddScoped<INotificationService, ClientNotificationService>();
四、可选:优化MainLayout的事件处理
虽然async void在Blazor事件处理中允许,但可以调整为更安全的写法(可选):
public async Task OnNotify() { notifications = await NotificationService.GetNotifications(); StateHasChanged(); } // 订阅事件时改为: NotificationService.OnChange += async () => await OnNotify();
进阶方案:实时多客户端通知
如果需要多个客户端实时接收通知(如用户A发通知,用户B能立刻看到),需要用SignalR实现推送:
- 服务端添加SignalR Hub,在
NotificationService的StateChanged方法中调用Hub推送消息给所有客户端。 - 客户端连接SignalR Hub,收到消息后触发
ClientNotificationService的OnChange事件。 - MainLayout订阅事件刷新UI。
内容的提问来源于stack exchange,提问作者Mat
相关产品推荐
相关产品推荐

