Table of Contents

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/ exposes 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.cs maps eight hub endpoints. Anything not in that list is unreachable however complete its class looks — see the trap under Execution/ below.
  • The tree is not self-contained. The project service types Program.cs leans on hardest live in the sibling HiNc engine repository, not here.

Program.cs also holds the hooks through which another project hosts the web service — see Host Hooks below.

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, the project's step variables and color trees, run-output queries, and the real-time push layer.

  • Execution/ExecutionController.cs — the playback surface.
  • Execution/ExecutionChartsController.cs and Execution/ClStripController.cs — the chart data. Three separate classes share the case-insensitive api/execution prefix 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 that Program.cs resolves eagerly, so it subscribes to its sink before the first client connects.
  • Execution/ClStripHub.cs, Execution/ExecutionStatusHub.cs — the strip and status pushes.
  • Execution/StepVariableController.cs — the project's step variables: the list, an add, change or rename, a delete, the compile-only check and the preview.
  • Execution/StepColorTreeController.cs — the project's color trees: the list, an add, change or rename, a delete, the check and the preview.
  • Execution/ExecutionStatusService.cs — the status broadcast behind that hub, and also the service log's engine-message lines under the four Hi.Engine.* categories and its run-start and run-end lines.
  • The Execution canvas has no hub of its own: it rides Disp/RenderingHub.cs like every other canvas.

Documented in Execution Page, Program Branch, Block Info Panel, Step Variables Branch, Step Colors Branch, Selected-Step Info Panel, Strip Charts, Cycle-Line Charts and — for the log lines — Log Viewer Page.

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, ambient 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 the scan that answers whether the loaded project actually plays CSV or CL — the referenced flag the Preference menu captions its CSV and CL Controller checkboxes with; the two tree nodes follow those device-local checkboxes, not the scan. No SignalR hub lives here.

  • Mech/Topo/ — one thin controller per transformer kind, each editing an instance held in the keyed object store. Documented in Transformer Select Panel.
  • Mech/Topology/ — the equipment topology editor behind the Equipment page's Topology column, not to be confused with Mech/Topo/: Mech/Topology/EquipmentTopologyController.cs is the one REST surface (api/mech/equipment-topology), Mech/Topology/EquipmentRoles.cs the per-part role table with the webservice's own checks, Mech/Topology/TopologyEditService.cs the anchor / branch / transformer / solid editing that controller builds per request, and Mech/Topology/TopologyGraphDto.cs with Mech/Topology/TopologyGraphBuilder.cs the whole-equipment graph. Documented in Equipment Topology.
  • 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.cs and Mech/ClRunnerController.cs — the two resident non-brand runner suits, reached from two Equipment tree nodes that are absent until their checkboxes in the Preference menu's Optional Nodes & Charts submenu are ticked, or a link names them. Documented in Hidden Controller Branches.

Documented in Equipment 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.cs is 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, service-wide 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, and read this instance's file through the file log provider; the same controller writes one log line per completed project operation.

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 with the line index that pages a large text file and the CSV chart service behind api/csv-strip, path guards, the per-instance daily file logger (the File provider the Log Viewer reads), and two pieces the whole application rests on. Common/IndexService.cs is the keyed object store behind the index a backend object, then edit it by key pattern every geometry, transformer and widget controller uses — one process-wide store that every browser and script connected to the service shares. Common/CleanupHub.cs is not a messaging hub; it is one of the two things that bound that store. Its key registry is a static dictionary bucketed by connection id (SignalR builds a fresh hub instance for every invocation, so an instance field could not carry a key to the disconnect), and 90 seconds after a connection drops the sweep evicts every key it registered with Add that no live connection holds by then — a reconnected page registers its keys again, so a transient drop costs it nothing. The browser bounds the store from the other side: wwwroot-src/src/composables/useCleanupHub.ts posts the index-remove endpoint on Common/IndexController.cs for every key it holds when its host unmounts, and again whenever a key it registered is replaced. Documented in Object Store (IndexService), 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 4×4 matrix, and the object-management surface that handles file operations, XML editing and copy-paste for indexed objects. The 3D vector has no controller of its own: its widget posts to the owner of the vector, a transformer controller under Mech/Topo/ or the box controller under Geom/. Documented in Object Management Menu Button, Mat4dControl Component and, for the vector, Vec3dControl Component.

Host Hooks

Program.cs carries the hooks through which another project hosts the web service: two static properties whose null defaults are the web service running on its own, and two public methods.

  • ContentRootPath — null: the content root, where the settings files and wwwroot are read from, is the working directory, or --contentRoot on the command line.
  • ConfigureBuilder — null: nothing is added to the builder before BuildApp reads its first setting and registers its first service.
  • AnnounceWhenStarted — once the server listens, prints the version and settings file it is given, the addresses and the working directory, and on Windows puts the address in the console window's title; under systemd (INVOCATION_ID set) it leaves out the addresses and the line saying that closing the window stops HiNC. It opens no browser.
  • RunApp — runs what BuildApp built, then ends the native core and closes the log file.

The web service's own Main applies the Linux core-dump filter, then calls BuildApp, AnnounceWhenStarted and RunApp. Execution/ExecutionStatusService.cs makes StatusRunning and StatusPaused public constants for a host that checks for a run in progress, and the front end's counterpart is the build-time product alias in wwwroot-src/quasar.config.ts, covered in Web Service SPA Source Tree. Documented in Hosting from another project.

Controller and Demo

Controller/ is the single-file surface over the legacy HardNcEnv model, MachiningProject.NcEnv. No page in the app drives it, 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 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