Web Service Backend Source Tree
The C# half of HiNC-2025-webservice is an ASP.NET Core process that serves the SPA, answers its
REST calls, and pushes to it over SignalR. It is organised by the engine's domain vocabulary, not
by web-framework artifact type: a controller, its hub, its DI service and its non-web scene objects
sit together in one domain folder rather than in a Controllers / Hubs / Services split.
Folders below are ordered by how much of the shipped surface they answer for.
Reading a Filename
The role of a file is told by its suffix and base type, and the convention holds throughout:
| Suffix | What it is |
|---|---|
*Controller.cs |
a REST controller with a route attribute |
*Hub.cs |
a SignalR hub — but see the two traps below |
*Service.cs |
a singleton registered in Program.cs |
*Displayee.cs |
a scene-composition object handed to the engine; no HTTP surface at all |
*Dtos.cs, *Config.cs |
plain wire or settings types |
Two names deliberately break the reader's expectation. Controller/ControllerController.cs means
CNC controller, not an MVC controller. And Mech/'s *DisplayController.cs files are ordinary
REST controllers that attach a displayee to a rendering connection somebody else already owns — they
are not hubs.
Important
Folder nesting does not predict the route. Mech/Topo/ and Mech/MechBuilder/ expose routes
that carry no api/mech/ prefix at all, and even inside Mech/ two conventions coexist: the newer
ports use kebab-case paths under api/mech/, while the older keyed-object editors use the
controller-name default. Read the route attribute, never the path.
Composition Root
Program.cs is the only C# file at the repository root, and it is where the questions a reader
usually has are actually answered: which services are singletons, which hubs are mapped, and what the
middleware order is. Two facts about it are worth carrying:
- A declared hub is not a mapped hub.
Program.csmaps eight hub endpoints. Anything not in that list is unreachable however complete its class looks — see the trap underExecution/below. - The tree is not self-contained. The project service types
Program.csleans on hardest live in the sibling HiNc engine repository, not here.
Documented in Program and Hosting.
Execution
Execution/ is the run cockpit's whole backend: playback control, the strip and cycle-line charts,
the NC-program branch index, run-output queries, and the real-time push layer.
Execution/ExecutionController.cs— the playback surface.Execution/ExecutionChartsController.csandExecution/ClStripController.cs— the chart data. Three separate classes share the case-insensitiveapi/executionprefix on purpose, one of them routed there rather than under Mission with a comment saying why.Execution/SessionSinkHub.cs— four mapped hubs declared in one file, one per message sink, so hub-per-file does not hold here. Each pairs with a broadcast service thatProgram.csresolves eagerly, so it subscribes to its sink before the first client connects.Execution/ClStripHub.cs,Execution/ExecutionStatusHub.cs— the strip and status pushes.
Warning
Execution/ExecutionCanvasHub.cs declares a hub that Program.cs never maps and that nothing in
the repository references. The Execution canvas rides Disp/RenderingHub.cs like every other
canvas. A reader looking for “the hub behind the Execution page” by name will find this file first
and be wrong.
Documented in Execution Page, Program Branch, Selected-Step Info Panel, Strip Charts and Cycle-Line Charts.
Mech
Mech/ is the largest domain folder: the REST surfaces for the machine tool, the tool house and
cutter editing, fixtures and workpieces, spindle capability, background and coolant, and the three
runner suits. It also holds the display controllers that bind a mechanism scene onto a rendering
connection. Mech/CutterDtoBuilder.cs is the shared read-side DTO shape two controllers reuse, and
Mech/NcSuitUsage.cs is what lets the Control Tree show the CSV and CL runner branches only when the
loaded project actually plays them. No SignalR hub lives here.
Mech/MechBuilder/— the standalone mechanism-building session, held by a process-wide singleton rather than per user. Documented in Mechanism Builder Page.Mech/Topo/— one thin controller per transformer kind, each editing an instance held in the keyed object store. Documented in Transformer Select Panel.Mech/SoftNcRunnerController.cs— the one endpoint family behind the Controller branch, and the file whose snapshot decides which of that branch's nodes exist. Documented in Controller Branch, with Brand Matrix for the snapshot flags themselves.Mech/CsvRunnerController.csandMech/ClRunnerController.cs— the two resident non-brand runner suits, reached from tree branches the Preference menu hides by default. Documented in Preference Menu Dropdown until those branches have a page.
Documented in General Setup Page and Tool House Page and the panels beneath them.
Missions
Missions/ is the mission command tree's backend. Two things here surprise readers:
- The folder is plural and the route is singular — and the SPA folder is singular too.
Missions/NcOptOptionEndpoints.csis not a minimal-API endpoint file despite the name. It is a second file of the same partial controller class, which is why its routes resolve under the mission prefix.
Missions/MissionCommandCatalog.cs reflects over every session command carrying the catalog
attribute once per process, replacing hand-maintained kind switches, and
Missions/MissionCommandFields.cs does the same for annotated scalars — which is how a simple
command gets an editor without a bespoke panel. Missions/ScriptCompletionService.cs and
Missions/ScriptCompileCheckService.cs are the Roslyn pair behind the script editor; the compile
check reuses the same options and globals type the script command uses at run time.
Documented in Mission Root Panel and the command panels under it.
Disp
Disp/ is the rendering layer. Disp/RenderingHub.cs is the single transport surface for every 3D
canvas in the application — canvas initialization, pointer, key and touch input, resize, view
presets, cache clearing and snapshots — and the SPA's canvas component defaults to it, so all pages
share one hub rather than one hub per page. Disp/RenderingService.cs owns the per-connection
engines the hub resolves against. Disp/StlPreviewController.cs is the only other REST surface here.
The *Displayee.cs files are scene-graph composition objects rather than web types, and each has a
live instantiation site: the execution scene, the equipment-setup scene, the step-subtraction scene
and the two coordinate-frame displayees the first two compose in.
Documented in Rendering Canvas on Web Service,
RenderingCanvas Tool Bar and — for
Disp/StlPreviewController.cs and the per-connection slot behind it —
STL Preview Pane.
Environments
Environments/ is session and environment scope: the project lifecycle, per-user preference
persistence, the Execution page's division flags, and the shipped localized step-present catalog. It
is also where the Log Viewer's data comes from — the log endpoints sit on the project controller
beside status, new, load, save, reload, save-as and close.
Documented in Main Panel, Session State, Preference Menu Dropdown, Internationalization, Log Viewer Page and Step Present Dialog.
Common, Geom and Widget
Common/— cross-cutting infrastructure with no single domain owner: the optional login gate, the named-root file explorer, path guards, the daily file logger, and two pieces the whole application rests on.Common/IndexService.csis the keyed object store behind the index a backend object, then edit it by key pattern every geometry, transformer and widget controller uses.Common/CleanupHub.csis not a messaging hub, and it is not what bounds that store either. Its key registry is an ordinary instance property and SignalR builds a fresh hub instance for every invocation, so the entryAddrecords is discarded with the instance that received it and the disconnect handler always walks an empty registry. The bound comes from the browser instead:wwwroot-src/src/composables/useCleanupHub.tsposts the index-remove endpoint onCommon/IndexController.csfor every key it holds when its host unmounts, and again whenever a key it registered is replaced. Documented in Dictionary Service Pattern, WebAPI Hub Cleanup Pattern, Login and Authentication and Log Viewer Page.Geom/— one CRUD controller per geometry kind, on the same keyed-object pattern, and nothing else: no hubs, no services. Documented in Geometry Panels.Widget/— the generic value and lifecycle controllers the reusable inputs post to: the 3D vector, the 4×4 matrix, and the object-management surface that handles file operations, XML editing and copy-paste for indexed objects. Documented in Object Management Menu Button, Vec3dControl Component and Mat4dControl Component.
Controller and Demo
Controller/ is the single-file surface over the legacy HardNcEnv model, MachiningProject.NcEnv.
The Legacy Controller page that drove it was removed on 2026-09-11, but the controller is still
mounted: its routes edit the legacy tables, a different store from the runner tables that
Mech/SoftNcRunnerController.cs — its successor, as that file's own doc comment says — edits. The
successor covers the brand, the axis limits and rapid feedrates, the tooling time, the work
coordinates, the datum tables and the tool offsets, but not every route — among them the work-coordinate Align
P0 pair, the shortest-rotary toggle, the per-axis max rotary speed and the Heidenhain master-axis
character have no soft-runner endpoint. Only GET cnc-brand still has a client — the Execution
tool bar's Heidenhain Coordinate gate. Documented in Legacy Controller Model (HardNcEnv).
Demo/ is customer-facing sample code — a custom colour guide and a per-step optimization sweep —
compiled into the assembly with no call site in the running application. Read it as an example of
how to extend the engine, not as part of the shipped behaviour.
See Also
- Anatomy by Source Directory — the other two source trees, and how this layer is meant to be entered
- Web Service SPA Source Tree — the front end this process serves and answers