Skip to content

Real-Time Updates (SignalR)

Added in: Cesivi v253.0 (PLAN-916 / PLAN-917)


Overview

Cesivi WebUI supports real-time change notifications via SignalR. When one user creates, updates, or deletes a list item, all other users viewing the same list automatically receive a notification and their browser refreshes to show the latest data — without requiring a manual page reload.

This feature works across browser tabs and separate browser sessions on the same machine, as well as across machines connected to the same Cesivi.Server.


Supported Pages

Page Real-Time Updates
AllItems (list view) ✅ Auto-refresh on item create/update/delete
NewForm ❌ Not applicable (single-session form)
EditForm ❌ Not applicable (single-session form)
DispForm ❌ Not yet
Site home page ❌ Not yet

Note: Future versions may extend real-time updates to DispForm and the site home page.


How It Works

Architecture

User A (browser)                Cesivi.Server              User B (browser)
    │                               │                           │
    ├─ REST POST /items ────────►   │                           │
    │                           ChangeNotificationService       │
    │                           sends to SignalR group          │
    │                               │ ◄── WebSocket ──────────► │
    │                               │                    CesiviRealTime.js
    │                               │                    receives event
    │                               │                    shows toast
    │                               │                    reloads page (600ms)
    │                               │                           │

Group Naming

SignalR groups are scoped per list:

  • Root web, list "Tasks" → group key: list::Tasks
  • Sub-web "subweb", list "Documents" → group key: list:subweb:Documents

The browser joins the correct group when the AllItems page loads.

Event Types

Server Event SignalR Message Description
Item created/updated/deleted ListItemChanged Individual item CRUD operations
List created/deleted ListChanged Structural list changes
File created/updated/deleted FileChanged Document library file changes

User Experience

Connection Indicator

A small colored dot appears next to the list title:

  • 🟢 Green — Real-time updates connected
  • 🟡 Amber — Reconnecting after network interruption
  • Grey — Disconnected (updates will not be received)

Toast Notification

When another user makes a change, a brief notification banner appears at the top of the page:

Item updated by another user — refreshing…

The banner auto-dismisses after 6 seconds. The page automatically reloads 600ms after the notification, so the banner is typically visible for less than 1 second before the page refreshes.

Auto-Refresh Behavior

  • Changes are debounced — if multiple users make changes within 600ms, a single reload is triggered.
  • The reload preserves the current page URL (including sort, filter, and pagination state).
  • The reload is a full page reload (window.location.reload()), not a partial table update.

Configuration

Real-time updates require no additional configuration when Cesivi.Server and Cesivi.WebUI are running on the same host. The WebUI automatically reads the server URL from appsettings.jsonCesiviClient:BaseUrl and passes it to the SignalR client.

Behind a Reverse Proxy

If WebSockets are blocked by a proxy, SignalR falls back automatically to: 1. Server-Sent Events (SSE) 2. Long Polling

No configuration change is required — SignalR negotiates the best transport automatically.

If real-time updates must be disabled entirely (e.g., for compliance reasons), the feature degrades gracefully: no errors, no disruption to normal operation — the page simply will not auto-refresh.

CORS

Cesivi.Server is configured with SetIsOriginAllowed(_ => true) + AllowCredentials() to support WebSocket connections from any origin. This is appropriate for development environments. For production, restrict the allowed origins in Program.cs CORS policy.


Troubleshooting

Indicator is Grey (Disconnected)

  1. Verify Cesivi.Server is running and reachable at the configured URL.
  2. Check browser console (F12) for SignalR connection errors ([CesiviRealTime] prefix).
  3. Verify firewall rules allow WebSocket connections (port 5010 by default).
  4. Check if a proxy is stripping Upgrade: websocket headers. SSE/long polling should still work as fallbacks.

No Auto-Refresh Happening

  1. Check the connection indicator — if grey, see above.
  2. Confirm the item was saved via the WebUI or REST API (direct database edits bypass notifications).
  3. Check browser console for JavaScript errors.

Excessive Page Reloads

If the AllItems page refreshes frequently without visible changes: - Check if another automated process or integration is making frequent background API calls. - The REFRESH_DEBOUNCE_MS = 600 value in realtime-updates.js can be increased to reduce reload frequency.


Technical Details

JavaScript Client

The SignalR client lives in wwwroot/js/realtime-updates.js and exposes:

CesiviRealTime.init(serverUrl, webContextPath, listName, onChangeCb);
CesiviRealTime.disconnect();
CesiviRealTime.reconnect();

Auto-reconnect delays: [0ms, 2s, 5s, 10s, 30s]

Server-Side

  • Hub class: Cesivi.Server.Hubs.ChangeNotificationHub
  • Hub endpoint: /signalr/changes
  • Hub methods: JoinListGroup, LeaveListGroup, JoinWebGroup, LeaveWebGroup
  • Notification service: Cesivi.Server.Services.ChangeNotificationService (implements IChangeNotifier)
  • Storage integration: StorageServiceWithPlugins fires notifications after every SaveListItemAsync, DeleteListItemAsync, SaveListAsync, DeleteListAsync, DeleteFileAsync
  • Notifications are fire-and-forget — they never block or delay storage operations

Documentation for Cesivi v253.0