Skip to main content

Files, Reports, and Browser Boundaries

The import that read C:\Orders\in.csv becomes Upload → configured storage root → importer → the reused business logic, Export to Excel becomes a managed .xlsx + Application.Download, Print Invoice becomes a server PDF in a PdfViewer, and long reports go through a process-wide report queue (progress, cancel, view, download) that every browser session sees.

Run it

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

Then open http://localhost:5606. (Visual Studio: open OrderDesk.slnx, F5.) No Office, no printer needed.

There is no login in this module: the first session of the process acts as kelly, every later one as sam (Application.Session.User), so the queue's Owner column can show two users.

What to try

ActionWhat you should see
Upload order-batch.csv… → pick OrderDesk.Web/wwwroot/samples/order-batch.csvorder-batch.csv → 5 order(s) saved, 0 skipped, a toast, and orders 1043–1047 at the top of the invoice list (Tailspin Toys 5,652.50 after its 5 % discount). The file is stored under App_Data/uploads/
Upload a non-.csv or a file over 1 MBa warning toast; nothing is imported
Pick an order → Print Invoice (PDF)the invoice PDF, built on the server, opens in a modal PdfViewer with a Download button
Export .xlsx ⬇the browser saves Orders.xlsx (sheet "Orders"), written without Office under App_Data/exports/
Queue Q2 summarya job appears (Running, then Done after ~3 s); View result ▸ opens it, Download result ⬇ saves it
Queue invoice batch ×1,204, then Queue monthly statementthe batch runs (~36 s, progress climbing) while the statement waits; the page stays responsive. Cancel selected stops the batch and the statement starts
Open second session ↗ → queue a job therethe new tab (owner sam) sees the same queue; the job appears in both tabs within a second

Where things live

Module 6/
└─ OrderDesk.Web/ the Wisej.NET 4 app (net10.0-windows;net10.0), port 5606
├─ Program.cs / Startup.cs session entry point (Application.MainPage) / Kestrel host (app.UseWisej())
├─ Default.html / Default.json / Web.config ← appSettings OrderDesk.StorageRoot = "App_Data"
├─ Domain/ the reused business logic (OrderService.Save computes the imported totals)
├─ Files/StorageRoot.cs the configured root: Path.Combine(Application.StartupPath, …), uploads/ exports/ reports/, SafeFileName
├─ Files/OrdersCsvImporter.cs Stream → orders (two layouts) → CustomerService.FindByName + OrderService.Save
├─ Reporting/ReportService.cs CreateOrdersWorkbook(rows) → path · CreateInvoicePdf(order) → bytes
├─ Reporting/XlsxWriter.cs dependency-free .xlsx (ZipArchive + five OpenXML parts)
├─ Reporting/InvoicePdfWriter.cs dependency-free PDF (+ WritePages for batches)
├─ Reporting/ReportQueue.cs process-wide queue: one lock, one Task.Run worker, progress, cancel
├─ Reporting/ReportBuilders.cs the three jobs (invoice batch, monthly statement, Q2 summary)
├─ Views/InvoicePreviewForm.cs PdfViewer + Download in a modal Form (caller disposes)
├─ Views/Ui.cs colours + toast helper
├─ wwwroot/samples/order-batch.csv the sample import file (8 rows → 5 orders)
├─ MainPage.cs / .Designer.cs import, invoice, export and the report queue
├─ App_Data/ created at run time: uploads/, exports/Orders-<stamp>.xlsx, reports/<id>-<name>.pdf
└─ docs/ the lab deliverables + migration-log.md

Runtime facts

  • Upload: Wisej.Web.Upload is a button that opens the browser's picker; AllowedFileTypes = ".csv" and MaxFileSize = 1048576 filter on the client (Error fires with FileTooLarge), the server validates again. Uploaded delivers e.Files[i] with FileName, ContentLength, ContentType, InputStream.
  • PdfViewer: PdfStream = new MemoryStream(bytes) inside a Form shown with ShowDialog((form, result) => form.Dispose()).
  • Download: Application.Download(path, name) streams a file from the server disk; Application.Download(stream, name) streams bytes in memory.
  • The queue worker never touches controls. It runs in Task.Run, outside any Wisej session; pages poll it with a Wisej.Web.Timer and redraw only when ReportQueue.Signature() changes.
  • Paths: Path.Combine(Application.StartupPath, "App_Data", …) everywhere; Web.config OrderDesk.StorageRoot may be relative or absolute.
  • The projects multi-target net10.0-windows;net10.0, so dotnet run needs -f net10.0 (or -f net10.0-windows). Delete App_Data/ to reset uploads, exports and report results.