Skip to main content

Workflow UX: Wizards, Modal Orchestration & Compensation

The Escalation Wizard — six steps (Reason · Attachments · Approver · Due date · Notifications · Review) opened modally with ShowDialogAsync — fills one typed EscalationCommand, and EscalationWorkflow : IEscalationWorkflow executes the whole transition (validate → authorize → persist → notify → audit) and returns one typed WorkflowResult.

The failure path is: the notification fails after the persist succeeded. The escalation is kept, a compensation is recorded in the manual-review queue, the audit entry explains the gap, and the queued entry can be retried later. The simulated failure lives in FakeNotificationGateway: its SMTP relay times out on the first e-mail of the session and delivers every send after that.

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

Run it

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

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

Requirements: .NET 10 SDK, the Wisej-4 4.1.0 NuGet package. dotnet build -nologo -v q passes for both target frameworks with 0 warnings and 0 errors.

What's on screen

  • Work queue (WorkQueuePage): header title, the queue grid (dgvWorkQueue), Escalate work order… (btnEscalate), a message banner (lblBanner), and the manual-review queue (lstCompensation) with Retry notification (btnRetryNotification).
  • Escalation Wizard (EscalationWizard, modal): the steps rail (stepsRail), one panel per step, lblValidation, Cancel / Back / Next (Next becomes Finish on Review, Close after it), and the dark status strip (lblWizardStatus) under the wizard.

What to click

ActionPathWhat you should see
Select WO-100232 (Critical) → Escalate work order… → six steps → Finish (first e-mail of the session)failure + compensationamber banner "Escalation created — approver NOT notified.", persist ✓ · notify ✕ · CompensationAction: manual-review queued (#1), the WorkflowResult line in the status strip; after Close the row is Escalated and the manual-review queue has an open entry. The escalation is kept.
Select the open entry → Retry notificationrecoverythe notification is re-sent, the entry is resolved, escalation.notify.retried is audited under a new correlation id
Escalate another work order → Finishsuccessgreen banner "Escalation created and approver notified."
Next with an empty reasonvalidationstays on step 1: "Reason: a reason is required", nothing persisted
Critical row, Next on step 2 with no filevalidation"a Critical escalation needs at least one attachment"
ben.tech as approver → Nextvalidation (security)"ben.tech is a Technician — only Supervisors and Managers approve"
ana.ops as approver → Finishvalidation at the commandEscalateAsync returns ValidationFailed ("you cannot approve your own escalation") and the wizard jumps back to step 3 because result.FirstFailingStep said so
Cancel → Yes, then Escalate… againresumethe wizard reopens on the same step with every answer; the status strip says Draft resumed
Cancel → Nocanceldraft removed, staged uploads cleaned up; nothing was persisted

Where things live

Module 7/
├─ EnterpriseOps.slnx
└─ EnterpriseOps/
├─ UI/
│ ├─ WorkQueuePage.cs / .Designer.cs the queue + the manual-review queue
│ └─ EscalationWizard.cs / .Designer.cs the modal wizard: stepsRail + six panels + Cancel/Back/Next
├─ Services/
│ ├─ SessionServices.cs per-session composition root (page + wizard share it)
│ ├─ SessionContext.cs ActivityTrace.cs (server log) WorkQueueRow.cs
│ └─ Workflow/ IEscalationWorkflow, EscalationWorkflow, EscalationCommand,
│ WorkflowResult, EscalationWizardState, WorkflowStateStore,
│ CompensationLog, WizardStep, StepValidation, WorkflowProgressObserver
├─ Domain/ WorkOrder.cs, Escalation.cs (+ Attachment, Approver, NotificationChannels)
├─ Data/ InMemoryWorkOrderStore, InMemoryEscalationStore, AttachmentStaging, SeedData (48 rows)
├─ Security/ UserRole.cs, PermissionService.cs, AuditLog.cs
├─ Integrations/ INotificationGateway + Fake (SMTP timeout on the first e-mail), IApproverDirectory + Fake
├─ docs/ the five deliverables + the SVG + the production-readiness note
├─ Program.cs Application.MainPage = new UI.WorkQueuePage()
└─ Startup.cs Kestrel host (app.UseWisej())