You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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实现推送:

  1. 服务端添加SignalR Hub,在NotificationService的StateChanged方法中调用Hub推送消息给所有客户端。
  2. 客户端连接SignalR Hub,收到消息后触发ClientNotificationService的OnChange事件。
  3. MainLayout订阅事件刷新UI。

内容的提问来源于stack exchange,提问作者Mat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:47:12