Complex Data Widgets
An editable grid (WorkOrderGrid : Widget, Kendo-style DataSource → the widget's postback URL)
and a read-only pivot (WorkOrderPivot : Widget, DevExtreme-style CustomStore → a [WebMethod]
on the page) feed the same vendor-free server contract — GridOperationRequest,
GridDataController.Handle(action, …), WorkOrderStore. Two vendors, one pattern.
The "vendor" libraries are small stand-ins written in the style of the real ones (VendorGrid,
VendorPivot); nothing is fetched from a CDN. Nothing here is deployed anywhere; it is a plain
Wisej.NET 4 project on this machine.
Run it
cd "LearnWisej-Samples/Application Integration Course/Module 9/IntegrationLab"
dotnet run -f net10.0 --urls http://localhost:5079
Then open http://localhost:5079. (Visual Studio: open IntegrationLab.slnx, press F5 — the
launch profile already uses port 5079.)
Requirements: .NET 10 SDK, the Wisej-4 4.1.0 NuGet package.
dotnet build -nologo -v q passes with the expected CS7022 warning only.
What to try on the "IntegrationLab — Data Widgets" page
Everything happens in the two widgets; the Remote operations card on the right lists each operation and event as it reaches the server.
| Gesture | What you should see |
|---|---|
| (page load) | ← JS→.NET load {skip:0,take:20} → 200 (20/150) and ← JS→.NET LoadPivot (WebMethod) {…} → 200 (5×4, N cells) |
| the grid's ‹ › pager | load {skip:20,take:20} → 200 (20/150) (remote paging) |
| a click on a column header | load {…,sort:"status asc"} → 200 (remote sort); click again for desc |
| double-click a cell, edit, Enter | rowUpdated {rowKey:"WO-1043",changes:{status:"Closed"}} (+ toast), then update {…} → 200 WO-1043 saved |
type abc into an Hours cell | update {…} → 400 hours must be a number …, then error {phase:"update",status:400,…} and an error toast |
| + Add row, fill in, save | create {"values":{…}} → 200 → WO-1151, followed by a reload |
| a row's ✕ | destroy {"rowKey":"WO-1010"} → 200 WO-1010 removed (149 left) |
| click a grid cell / a pivot cell | cellClick {rowKey,field,value} / cellClick {rowKey,columnKey,value} |
Where things live
IntegrationLab/
├─ Contracts/
│ ├─ GridOperationRequest.cs Skip / Take / Sort[] / Filter[] (+ SortDescriptor, FilterDescriptor)
│ ├─ GridOperationResult.cs Rows / Total / Skip / Take
│ ├─ RowOperationRequests.cs RowUpdateRequest { RowKey, Changes } · RowInsertRequest { Values } · RowDeleteRequest { RowKey }
│ ├─ PivotContracts.cs PivotRequest { RowField, ColumnField, Measure } · PivotResult · PivotCell
│ ├─ OperationResult.cs Status / Body / Summary · DataContractException(400|404)
│ ├─ WidgetEventArgs.cs CellClickEventArgs · RowUpdatedEventArgs · PivotCellClickEventArgs · DataWidgetErrorEventArgs · TraceEventArgs
│ └─ JsonCodec.cs camelCase JSON in/out, JsonElement / DynamicObject normalization
├─ Data/
│ ├─ WorkOrder.cs the row: id, asset, status, priority, assignee, hours, site
│ ├─ WorkOrderStore.cs in-memory store: Load / Insert / Update / Delete / Pivot with all validation
│ └─ GridDataController.cs Handle(action, args, body) — the one handler both entry points call
├─ Widgets/
│ ├─ WorkOrderGrid.cs typed properties, WebRequest (postback) handler, CellClick / RowUpdated events
│ ├─ GridColumn.cs typed column definition
│ └─ WorkOrderPivot.cs JSON-options prototype, CellClick / DataLoaded events
├─ wwwroot/
│ ├─ grid-init.js client adapter: Kendo-style DataSource → postback URL (embedded InitScript)
│ ├─ pivot-init.js client adapter: DevExtreme-style CustomStore → App.MainPage.LoadPivotAsync (embedded InitScript)
│ ├─ vendor-grid.js / .css the "third-party" editable grid (Package)
│ └─ vendor-pivot.js / .css the "third-party" read-only pivot (Package)
├─ docs/ the four deliverables
├─ MainPage.cs / .Designer.cs the lab page (Application.MainPage), [WebMethod] LoadPivot
├─ Program.cs Wisej.NET session entry point
└─ Startup.cs Kestrel host (app.UseWisej())