Skip to main content

Session, State, Tenant & Concurrency Design

A tenant-aware SessionContext that owns who the user is and which customer they are working in, a CommandContext with a correlation id on every command, a TenantGuard in every service, optimistic concurrency on work orders, and the ConflictDialog that explains a stale edit and offers Reload · Compare · Cancel.

Nothing here is deployed anywhere; it is a plain Wisej.NET 4 project that runs on your machine, with in-memory data.

Run it

cd "LearnWisej-Samples/Enterprise Wisej.NET Course\Module 3\EnterpriseOps"
dotnet run -f net10.0 --urls http://localhost:5203

Then open http://localhost:5203. (Visual Studio: open EnterpriseOps.slnx, press F5 — the port is in Properties/launchSettings.json.)

What to click

The screen: the header with cboTenant (only the tenants the signed-in user's claims entitle them to), the work queue for the current tenant (dgvWorkQueue, with a Version column), Open selected in editor, the editor (txtTitle, cboStatus, read-only txtVersion, Save), a banner for validation and errors, and the dark footer lblStatusBar.

ControlPathWhat you should see
Open selected in editorsuccesstxtVersion shows the token the record was loaded at, e.g. v7; footer Editing — expected version v7
Savesuccessfooter Saved — v7 → v8 · correlation …; the queue's Version column moves
Save (empty title)validationamber banner "A work order needs a title." — the service rejected it, nothing written
Save (after another tab saved)failure + recoveryfooter Save rejected — expected v7, found v8 · correlation …, then the conflict dialog
cboTenant → another tenantsuccessthe editor is dropped; the queue reloads with a different set of rows

In the conflict dialog: Reload latest (discard your edits, take the current record), Compare changes (field by field — the dialog stays open), Cancel (nothing saved, nothing lost, your edit stays on screen).

Reproduce the failure path

Open http://localhost:5203 in two browser tabs — two sessions, two SessionContext objects, one store.

  1. in both tabs select 2002 · Repair loading dock pump, click Open selected in editorv7;
  2. tab 1: change the status, click Save — the store moves to v8;
  3. tab 2: change the title to Repair loading dock pump — urgent, click Save — rejected, and the conflict dialog explains why;
  4. click Compare changes — Title, Status and Version differ;
  5. click Reload latest — the editor rebinds at v8, and the correlation ids tie every step to the audit log.

Where things live

Module 3/
└─ EnterpriseOps/
├─ UI/ WorkOrderEditorPage (queue + editor), ConflictDialog (Reload · Compare · Cancel)
├─ Domain/ WorkOrder (+ Version), ConcurrencyToken, Tenant, WorkOrderStatus, WorkQueueRow
├─ Services/ WorkOrderService, ConflictResolutionService, ConflictInfo, SaveWorkOrderCommand/Result,
│ WorkOrderEditModel, TenantDirectory, ServiceRegistry (per-session, no .Current)
├─ Security/ SessionContext, CommandContext, TenantGuard, AuditTrail, SharedStateAttribute,
│ IdentityProvider, VerifiedIdentity
├─ Data/ WorkOrderStore (shared, locked, clones on read), SeedData (2002 = the record)
├─ Diagnostics/ ActivityTrace (server log via System.Diagnostics.Trace), ErrorLog
├─ Resources/ UiText
└─ docs/ the five deliverables + the state ownership map