Skip to main content

Modernize, Secure, and Deploy the Capstone

The working port from Modules 1–6 is modernized (theme + mixin, tool buttons, watermark, toast) without touching the business logic, made responsive through ClientProfiles.json and three explicit layouts, secured as a web app (server-side sign-in and a permission check on every action, a download guard, AllowHtml only after a sanitizer, an audit log), given an operations dashboard and a health endpoint, and packaged with IIS / Docker deployment assets. The capstone report (reused · adapted · modernized · risks · next slice) closes the course.

The deployment files under deploy/ are written to be run, not executed by the sample.

Run it

cd "LearnWisej-Samples/From WinForms to the Web Course/Module 7/OrderDesk.Web"
dotnet run -f net10.0 --urls http://localhost:5607

Then open http://localhost:5607. (Visual Studio: open OrderDesk.slnx, F5.) GET http://localhost:5607/health answers JSON without a browser session.

What to try

ActionWhat you should see
Page load"OrderDesk" in Bootstrap-4 with the mixin's rounded buttons; the Orders tab shows 1042 Northwind Traders 4,820.00 Open first; the header says Not signed in
Toolbar New Orderorder 1043 (Litware, 1,280.00 — the same total as Module 1) at the top and a toast; the Dashboard KPIs move
Toolbar Print Invoicethe invoice PDF opens in a modal PdfViewer
Resize the browser below 1025 px, then below 601 pxtablet: short toolbar text and the detail below the grid; phone: the toolbar becomes an Actions… dropdown and the detail is hidden
Sign in kellyExportorders.csv downloads through the download guard (kelly is a Manager)
Sign in samExporta warning toast: 'orders.export' denied: role Clerk lacks 'orders.export' — the server checks every action
Type <b>Rush</b> order <img src=x onerror="alert(1)"> <i>ship Friday</i> into Order notethe preview shows Rush order ship Friday; the <img> is removed, nothing runs
Second session ↗ → sign in as sam there → back in the first tab, Dashboardthe recent-activity feed shows sam's sign-in within a second; ● live · 2 sessions
DashboardKPIs (Open orders, Revenue today, Invoiced, On-time %), the Orders by status chart and the audit-logged activity feed

Where things live

Module 7/
└─ OrderDesk.Web/ the Wisej.NET 4 app (net10.0-windows;net10.0)
├─ Program.cs / Startup.cs session entry point / Kestrel host + the /health endpoint (MapGet, no Wisej session)
├─ Default.html / Default.json / Web.config theme Bootstrap-4 · OrderDesk.StorageRoot, ThemeMixin, Version
├─ ClientProfiles.json Phone ≤600 · Tablet 601–1024 · Desktop ≥1025 (copied next to the assembly, never served)
├─ Themes/orderdesk.mixin.theme button + toolbar-button radius 14, orderdesk-accent colour
├─ Domain/ unchanged since Module 1 — the reused business logic
├─ Services/ResponsiveLayout.cs profile → Desktop / Tablet / Phone layout, in code
├─ Services/ThemeService.cs, AppConfig.cs
├─ Security/AuthService.cs SignIn (salted hashes) · Authorize / Demand per action · roles Manager / Clerk
├─ Security/DownloadGuard.cs permission → resolve under the storage root → exists → Application.Download
├─ Security/HtmlSanitizer.cs Encode · Sanitize (whitelist b, i, br)
├─ Security/AuditLog.cs process-wide append-only audit log with a Version counter
├─ Security/UserSessionContext.cs the per-session user (Module 4)
├─ Diagnostics/HealthCheck.cs the /health report
├─ Diagnostics/AppLog.cs App_Data/logs/orderdesk-yyyyMMdd.log + System.Diagnostics.Trace
├─ Reporting/ InvoicePdfWriter (server PDF), CsvExport (in-memory export)
├─ Views/ Ui, InvoicePreviewForm
├─ MainPage.cs / .Designer.cs sign-in header, Orders tab, Dashboard tab
├─ deploy/ IIS web.config, Dockerfile, docker-compose.yml, production settings notes
└─ docs/ the lab deliverables + migration-log.md

Runtime facts

  • Every Themes/*.mixin.theme file is merged over the Default.json theme at startup. Application.LoadTheme(name) swaps the theme object shared by every session in the process.
  • Application.ResponsiveProfileChanged is a static event: subscribe in Load, unsubscribe in Dispose, and check IsDisposed in the handler. ClientProfiles.json is read next to the assembly, so the csproj copies it to the output.
  • Label.AllowHtml = true sets the element's innerHTML: a user-entered <img onerror> executes in the browser. Encoding is the default; the sanitizer is the only path allowed to turn it off on user data.
  • Application.Download(path, name) is called with the resolved server path, never the browser's string.
  • /health is a plain ASP.NET Core endpoint (MapGet in Startup.cs) — no Wisej session is created for it.
  • The projects multi-target net10.0-windows;net10.0, so dotnet run needs -f net10.0 (or -f net10.0-windows).