Archived
301 lines
18 KiB
HTML
301 lines
18 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Web Service Backend Source Tree | HiAPI-C# 2025 </title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="title" content="Web Service Backend Source Tree | HiAPI-C# 2025 ">
|
||
|
||
|
||
<link rel="icon" href="../../img/HiAPI.favicon.ico">
|
||
<link rel="stylesheet" href="../../public/docfx.min.css">
|
||
<link rel="stylesheet" href="../../public/main.css">
|
||
<meta name="docfx:navrel" content="../../toc.html">
|
||
<meta name="docfx:tocrel" content="toc.html">
|
||
|
||
<meta name="docfx:rel" content="../../">
|
||
|
||
|
||
|
||
<meta name="loc:inThisArticle" content="In this article">
|
||
<meta name="loc:searchResultsCount" content="{count} results for "{query}"">
|
||
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
||
<meta name="loc:tocFilter" content="Filter by title">
|
||
<meta name="loc:nextArticle" content="Next">
|
||
<meta name="loc:prevArticle" content="Previous">
|
||
<meta name="loc:themeLight" content="Light">
|
||
<meta name="loc:themeDark" content="Dark">
|
||
<meta name="loc:themeAuto" content="Auto">
|
||
<meta name="loc:changeTheme" content="Change theme">
|
||
<meta name="loc:copy" content="Copy">
|
||
<meta name="loc:downloadPdf" content="Download PDF">
|
||
|
||
<script type="module" src="./../../public/docfx.min.js"></script>
|
||
|
||
<script>
|
||
const theme = localStorage.getItem('theme') || 'auto'
|
||
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
|
||
</script>
|
||
|
||
</head>
|
||
|
||
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
|
||
<header class="bg-body border-bottom">
|
||
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
|
||
<div class="container-xxl flex-nowrap">
|
||
<a class="navbar-brand" href="../../index.html">
|
||
<img id="logo" class="svg" src="../../img/HiAPI.logo.png" alt="">
|
||
|
||
</a>
|
||
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
|
||
<i class="bi bi-three-dots"></i>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navpanel">
|
||
<div id="navbar">
|
||
<form class="search" role="search" id="search">
|
||
<i class="bi bi-search"></i>
|
||
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
</header>
|
||
|
||
<main class="container-xxl">
|
||
<div class="toc-offcanvas">
|
||
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
|
||
<div class="offcanvas-header">
|
||
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
|
||
</div>
|
||
<div class="offcanvas-body">
|
||
<nav class="toc" id="toc"></nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="content">
|
||
<div class="actionbar">
|
||
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
|
||
<i class="bi bi-list"></i>
|
||
</button>
|
||
|
||
<nav id="breadcrumb"></nav>
|
||
</div>
|
||
|
||
<article data-uid="Anatomy-BySource-WebserviceBackend">
|
||
<h1 id="web-service-backend-source-tree">Web Service Backend Source Tree</h1>
|
||
|
||
<p>The C# half of <code>HiNC-2025-webservice</code> 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 <strong>engine's domain vocabulary</strong>, 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 <code>Controllers</code> / <code>Hubs</code> / <code>Services</code> split.</p>
|
||
<p>Folders below are ordered by how much of the shipped surface they answer for.</p>
|
||
<h2 id="reading-a-filename">Reading a Filename</h2>
|
||
<p>The role of a file is told by its suffix and base type, and the convention holds throughout:</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Suffix</th>
|
||
<th>What it is</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>*Controller.cs</code></td>
|
||
<td>a REST controller with a route attribute</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>*Hub.cs</code></td>
|
||
<td>a SignalR hub — but see the two traps below</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>*Service.cs</code></td>
|
||
<td>a singleton registered in <code>Program.cs</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>*Displayee.cs</code></td>
|
||
<td>a scene-composition object handed to the engine; no HTTP surface at all</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>*Dtos.cs</code>, <code>*Config.cs</code></td>
|
||
<td>plain wire or settings types</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Two names deliberately break the reader's expectation. <code>Controller/ControllerController.cs</code> means
|
||
<strong>CNC controller</strong>, not an MVC controller. And <code>Mech/</code>'s <code>*DisplayController.cs</code> files are ordinary
|
||
REST controllers that attach a displayee to a rendering connection somebody else already owns — they
|
||
are not hubs.</p>
|
||
<div class="IMPORTANT">
|
||
<h5>Important</h5>
|
||
<p><strong>Folder nesting does not predict the route.</strong> <code>Mech/Topo/</code> and <code>Mech/MechBuilder/</code> expose routes
|
||
that carry no <code>api/mech/</code> prefix at all, and even inside <code>Mech/</code> two conventions coexist: the newer
|
||
ports use kebab-case paths under <code>api/mech/</code>, while the older keyed-object editors use the
|
||
controller-name default. Read the route attribute, never the path.</p>
|
||
</div>
|
||
<h2 id="composition-root">Composition Root</h2>
|
||
<p><code>Program.cs</code> 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:</p>
|
||
<ul>
|
||
<li><strong>A declared hub is not a mapped hub.</strong> <code>Program.cs</code> maps eight hub endpoints. Anything not in that
|
||
list is unreachable however complete its class looks — see the trap under <code>Execution/</code> below.</li>
|
||
<li><strong>The tree is not self-contained.</strong> The project service types <code>Program.cs</code> leans on hardest live in
|
||
the sibling HiNc engine repository, not here.</li>
|
||
</ul>
|
||
<p>Documented in <a class="xref" href="../platform/program-and-hosting.html">Program and Hosting</a>.</p>
|
||
<h2 id="execution">Execution</h2>
|
||
<p><code>Execution/</code> 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.</p>
|
||
<ul>
|
||
<li><code>Execution/ExecutionController.cs</code> — the playback surface.</li>
|
||
<li><code>Execution/ExecutionChartsController.cs</code> and <code>Execution/ClStripController.cs</code> — the chart data.
|
||
Three separate classes share the case-insensitive <code>api/execution</code> prefix on purpose, one of them
|
||
routed there rather than under Mission with a comment saying why.</li>
|
||
<li><code>Execution/SessionSinkHub.cs</code> — <strong>four</strong> 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 <code>Program.cs</code> resolves
|
||
eagerly, so it subscribes to its sink before the first client connects.</li>
|
||
<li><code>Execution/ClStripHub.cs</code>, <code>Execution/ExecutionStatusHub.cs</code> — the strip and status pushes.</li>
|
||
</ul>
|
||
<div class="WARNING">
|
||
<h5>Warning</h5>
|
||
<p><code>Execution/ExecutionCanvasHub.cs</code> declares a hub that <code>Program.cs</code> never maps and that nothing in
|
||
the repository references. The Execution canvas rides <code>Disp/RenderingHub.cs</code> like every other
|
||
canvas. A reader looking for “the hub behind the Execution page” by name will find this file first
|
||
and be wrong.</p>
|
||
</div>
|
||
<p>Documented in <a class="xref" href="../execution/index.html">Execution Page</a>,
|
||
<a class="xref" href="../execution/program.html">Program Branch</a>,
|
||
<a class="xref" href="../execution/selected-step-info-panel.html">Selected-Step Info Panel</a>,
|
||
<a class="xref" href="../execution/strip-charts.html">Strip Charts</a> and <a class="xref" href="../execution/cycle-line-charts.html">Cycle-Line Charts</a>.</p>
|
||
<h2 id="mech">Mech</h2>
|
||
<p><code>Mech/</code> 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. <code>Mech/CutterDtoBuilder.cs</code> is the shared read-side DTO shape two controllers reuse, and
|
||
<code>Mech/NcSuitUsage.cs</code> 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.</p>
|
||
<ul>
|
||
<li><code>Mech/MechBuilder/</code> — the standalone mechanism-building session, held by a process-wide singleton
|
||
rather than per user. Documented in <a class="xref" href="../util/mech-builder.html">Mechanism Builder Page</a>.</li>
|
||
<li><code>Mech/Topo/</code> — one thin controller per transformer kind, each editing an instance held in the
|
||
keyed object store. Documented in
|
||
<a class="xref" href="../geom/transformer-panel.html">Transformer Select Panel</a>.</li>
|
||
<li><code>Mech/SoftNcRunnerController.cs</code> — the one endpoint family behind the Controller branch, and the
|
||
file whose snapshot decides which of that branch's nodes exist. Documented in
|
||
<a class="xref" href="../general-setup/controller/index.html">Controller Branch</a>, with
|
||
<a class="xref" href="../general-setup/controller/brand-matrix.html">Brand Matrix</a> for the snapshot flags themselves.</li>
|
||
<li><code>Mech/CsvRunnerController.cs</code> and <code>Mech/ClRunnerController.cs</code> — the two resident non-brand runner
|
||
suits, reached from tree branches the Preference menu hides by default. Documented in
|
||
<a class="xref" href="../shell/preference-menu.html">Preference Menu Dropdown</a> until those branches have a page.</li>
|
||
</ul>
|
||
<p>Documented in <a class="xref" href="../general-setup/index.html">General Setup Page</a> and
|
||
<a class="xref" href="../tool-house/index.html">Tool House Page</a> and the panels beneath them.</p>
|
||
<h2 id="missions">Missions</h2>
|
||
<p><code>Missions/</code> is the mission command tree's backend. Two things here surprise readers:</p>
|
||
<ul>
|
||
<li>The <strong>folder is plural and the route is singular</strong> — and the SPA folder is singular too.</li>
|
||
<li><code>Missions/NcOptOptionEndpoints.cs</code> 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.</li>
|
||
</ul>
|
||
<p><code>Missions/MissionCommandCatalog.cs</code> reflects over every session command carrying the catalog
|
||
attribute once per process, replacing hand-maintained kind switches, and
|
||
<code>Missions/MissionCommandFields.cs</code> does the same for annotated scalars — which is how a simple
|
||
command gets an editor without a bespoke panel. <code>Missions/ScriptCompletionService.cs</code> and
|
||
<code>Missions/ScriptCompileCheckService.cs</code> 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.</p>
|
||
<p>Documented in <a class="xref" href="../execution/mission/mission-root-panel.html">Mission Root Panel</a> and the command panels under it.</p>
|
||
<h2 id="disp">Disp</h2>
|
||
<p><code>Disp/</code> is the rendering layer. <code>Disp/RenderingHub.cs</code> 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. <code>Disp/RenderingService.cs</code> owns the per-connection
|
||
engines the hub resolves against. <code>Disp/StlPreviewController.cs</code> is the only other REST surface here.</p>
|
||
<p>The <code>*Displayee.cs</code> 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.</p>
|
||
<p>Documented in <a class="xref" href="../conventions/rendering-canvas-web-service.html">Rendering Canvas on Web Service</a>,
|
||
<a class="xref" href="../widget/renderingcanvas-tool-bar.html">RenderingCanvas Tool Bar</a> and — for
|
||
<code>Disp/StlPreviewController.cs</code> and the per-connection slot behind it —
|
||
<a class="xref" href="../util/stl-preview-pane.html">STL Preview Pane</a>.</p>
|
||
<h2 id="environments">Environments</h2>
|
||
<p><code>Environments/</code> 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.</p>
|
||
<p>Documented in <a class="xref" href="../shell/main-panel.html">Main Panel</a>,
|
||
<a class="xref" href="../platform/session-state.html">Session State</a>,
|
||
<a class="xref" href="../shell/preference-menu.html">Preference Menu Dropdown</a>,
|
||
<a class="xref" href="../platform/i18n.html">Internationalization</a>,
|
||
<a class="xref" href="../platform/log-viewer.html">Log Viewer Page</a> and
|
||
<a class="xref" href="../execution/step-present-dialog.html">Step Present Dialog</a>.</p>
|
||
<h2 id="common-geom-and-widget">Common, Geom and Widget</h2>
|
||
<ul>
|
||
<li><code>Common/</code> — 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. <code>Common/IndexService.cs</code> is the keyed object store behind the <em>index a backend object,
|
||
then edit it by key</em> pattern every geometry, transformer and widget controller uses.
|
||
<code>Common/CleanupHub.cs</code> is 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 entry <code>Add</code> records is discarded with the instance that received it and the
|
||
disconnect handler always walks an empty registry. The bound comes from the browser instead:
|
||
<code>wwwroot-src/src/composables/useCleanupHub.ts</code> posts the index-remove endpoint on
|
||
<code>Common/IndexController.cs</code> for every key it holds when its host unmounts, and again whenever a
|
||
key it registered is replaced. Documented in
|
||
<a class="xref" href="../conventions/dictionary-service-pattern.html">Dictionary Service Pattern</a>,
|
||
<a class="xref" href="../conventions/webapi-hub-cleanup-pattern.html">WebAPI Hub Cleanup Pattern</a>,
|
||
<a class="xref" href="../platform/login-and-auth.html">Login and Authentication</a> and
|
||
<a class="xref" href="../platform/log-viewer.html">Log Viewer Page</a>.</li>
|
||
<li><code>Geom/</code> — one CRUD controller per geometry kind, on the same keyed-object pattern, and nothing
|
||
else: no hubs, no services. Documented in <a class="xref" href="../geom/index.html">Geometry Panels</a>.</li>
|
||
<li><code>Widget/</code> — 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
|
||
<a class="xref" href="../widget/object-management-menu-button.html">Object Management Menu Button</a>,
|
||
<a class="xref" href="../widget/vec3d-control.html">Vec3dControl Component</a> and
|
||
<a class="xref" href="../widget/mat4d-control.html">Mat4dControl Component</a>.</li>
|
||
</ul>
|
||
<h2 id="controller-and-demo">Controller and Demo</h2>
|
||
<p><code>Controller/</code> is the single-file surface behind the legacy controller page. It has a successor in
|
||
<code>Mech/SoftNcRunnerController.cs</code>, whose own doc comment says so, but <strong>both are live</strong> — the legacy
|
||
page has not been removed. Documented in <a class="xref" href="../legacy-controller.html">Legacy Controller</a>.</p>
|
||
<p><code>Demo/</code> 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.</p>
|
||
<h2 id="see-also">See Also</h2>
|
||
<ul>
|
||
<li><a class="xref" href="index.html">Anatomy by Source Directory</a> — the other two source trees, and how this
|
||
layer is meant to be entered</li>
|
||
<li><a class="xref" href="webservice-spa.html">Web Service SPA Source Tree</a> — the front end this process
|
||
serves and answers</li>
|
||
</ul>
|
||
|
||
</article>
|
||
|
||
<div class="contribution d-print-none">
|
||
</div>
|
||
|
||
<div class="next-article d-print-none border-top" id="nextArticle"></div>
|
||
|
||
</div>
|
||
|
||
<div class="affix">
|
||
<nav id="affix"></nav>
|
||
</div>
|
||
</main>
|
||
|
||
<div class="container-xxl search-results" id="search-results"></div>
|
||
|
||
<footer class="border-top text-secondary">
|
||
<div class="container-xxl">
|
||
<div class="flex-fill">
|
||
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</body>
|
||
</html>
|