adas-core — API Host
ASP.NET Core Web API host for the ADAS Core platform.
This project is the Presentation Layer and application entry point. It composes all lower layers (Domain, Application, Infrastructure, Authentication, and Modules) via dependency injection, configures the HTTP pipeline, and exposes REST endpoints, WebSocket hubs, and OpenAPI documentation.
Table of Contents
- Overview
- Responsibilities
- Project Structure
- Dependencies
- Configuration Profiles
- Middleware Pipeline
- REST Endpoints
- WebSocket / SignalR Hubs
- Swagger & OpenAPI
- Serilog Bootstrap
- Build & Run
- Design Rules
Overview
The adas-core project is the executable ASP.NET Core application that hosts the entire ADAS backend. Its sole responsibility is to:
- Wire every layer and module into the dependency injection container.
- Load environment-specific configuration.
- Build the HTTP request pipeline (auth, CORS, error handling, routing).
- Expose REST controllers, WebSocket (SignalR) hubs, and Prometheus metrics.
- Bootstrap Serilog structured logging and Swagger API discovery.
It contains no business logic — all domain rules, use cases, and data access live in referenced projects.
Responsibilities
| Concern | What this project does |
|---|---|
| Composition Root | Registers all repositories, services, authentication strategies, MongoDB, Redis, and SignalR into IServiceCollection. |
| Configuration Loading | Loads layered appsettings.json files (base + environment-specific) using ConfigurationBuilder. |
| Pipeline Setup | Configures middleware order: auth, CORS, WebSockets, error handling, controllers, SignalR hubs. |
| API Exposure | Defines ASP.NET Core controllers that delegate to Application-layer services. |
| Real-Time Messaging | Hosts SignalR hubs (UciHub) for WebSocket-based push communication. |
| API Documentation | Auto-generates Swagger / OpenAPI specs with Newtonsoft.Json and ObjectId schema mapping. |
| Health & Metrics | Exposes /metrics (Prometheus) and Swagger UI at runtime. |
| Logging Initialization | Bootstraps Serilog from configuration with dynamic trace identifiers and contextual enrichers. |
Project Structure
adas-core/
├── Program.cs # Application bootstrap (DI registration + pipeline)
├── appsettings.json # Base configuration
├── appsettings.{Environment}.json # Environment-specific overrides (see list below)
├── Properties/
│ └── launchSettings.json # Launch profiles per environment
├── Configurations/
│ └── ServiceExtension.cs # Extension methods: JWT auth, ProxyDevices, config binding
├── Controllers/ # ASP.NET Core API controllers
│ ├── UserController.cs
│ ├── PatientController.cs
│ ├── DeviceController.cs
│ ├── AlarmController.cs
│ ├── LightBeaconController.cs
│ ├── ProxyDeviceController.cs
│ ├── RelayController.cs
│ ├── PumpsController.cs
│ ├── ObservationsController.cs
│ ├── TreatmentsController.cs
│ ├── DisplayController.cs
│ ├── ConfigObservationController.cs
│ ├── ConfigDisplayController.cs
│ ├── PointOfCareController.cs
│ ├── AdmissionController.cs
│ ├── DischargeController.cs
│ ├── AuditController.cs
│ ├── RabbitController.cs
│ ├── QXController.cs
│ ├── SendAlertController.cs
│ ├── SensorController.cs
│ ├── RecordingController.cs
│ ├── RecordingAlertController.cs
│ ├── ServiceConfigController.cs
│ ├── MasterListController.cs
│ ├── UnitController.cs
│ ├── NoticeController.cs
│ ├── MedicinesController.cs
│ ├── DiagnosisController.cs
│ ├── BoxController.cs
│ ├── CameraController.cs
│ ├── ApplicationController.cs
│ ├── GroupedObservationsController.cs
│ ├── PatientAppointmentController.cs
│ └── ...
├── ErrorMiddleware/
│ └── ErrorHandlerMiddleware.cs # Global exception-handling middleware
├── Logging/
│ ├── LogExecutionContext.cs # Ambient trace-identifier context
│ └── LogProvider.cs # Logger resolution helper
├── WebSocket/
│ ├── WebSocketMessageService.cs # WebSocket outbound message service
│ └── Hubs/
│ └── UciHub.cs # SignalR hub for real-time subscriptions
└── Dockerfile # Multi-stage Linux container image
Dependencies
Downstream References (this project depends on)
| Project | Role |
|---|---|
adas-core.Domain |
Domain entities, value objects, and repository contracts used by controllers for DTO mapping and route parameters. |
adas-core.Application |
Application services and DTOs invoked by controllers. |
adas-core.Infrastructure |
Infrastructure implementations registered in DI (repositories, MongoDB, Redis, messaging). |
adas-core.Authentication |
JWT middleware and authentication abstractions wired into the pipeline. |
adas-core.LdapLogin |
LDAP authentication strategy registered conditionally at startup. |
adas-core.LocalLogin |
Local database authentication strategy registered conditionally at startup. |
adas-core.module.LightBeacons |
Module controllers and services registered in DI. |
adas-core.module.ProxyDevices |
Module controllers and services registered in DI. |
adas-core.module.Relays |
Module controllers and services registered in DI. |
Upstream References (projects that depend on this)
| Project | Reason |
|---|---|
adas-core.Test |
Integration tests exercise the full host pipeline, controllers, and DI container. |
Configuration Profiles
The host supports multiple runtime environments via layered appsettings files. The base appsettings.json is always loaded first, then an environment-specific override is merged on top.
| Profile File | Environment | Typical Use |
|---|---|---|
appsettings.Local.json |
Local |
Developer workstation |
appsettings.Develop.json |
Develop |
Shared development server |
appsettings.LocalTest.json |
LocalTest |
Automated integration tests |
appsettings.H12O.json |
H12O |
Production site H12O |
appsettings.HRYCM.json |
HRYCM |
Production site HRYCM |
appsettings.HPAZ.json |
HPAZ |
Production site HPAZ |
appsettings.HPAZBastion.json |
HPAZBastion |
Bastion / DMZ instance |
appsettings.HUVH-UCIN.json |
HUVH-UCIN |
Hospital UVH UCIN ward |
appsettings.HUVH-UCIA.json |
HUVH-UCIA |
Hospital UVH UCIA ward |
appsettings.CHUO.json |
CHUO |
CHUO institution |
appsettings.CENTRAL_PHILIPS.json |
CENTRAL_PHILIPS |
Philips central integration |
appsettings.NursePlan.json |
NursePlan |
Nurse scheduling module |
appsettings.BombasBD.json |
BombasBD |
Infusion pump database |
appsettings.Auditoria.json |
Auditoria |
Audit / compliance instance |
appsettings.HGMM.json |
HGMM |
HGMM environment |
How profiles are resolved
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true)
.Build();
Set the active environment via the ASPNETCORE_ENVIRONMENT variable or a launchSettings.json profile.
Middleware Pipeline
The HTTP pipeline is assembled in Program.cs in the following order:
1. Swagger + SwaggerUI # API docs (dev/staging)
2. Static Files # Static assets
3. Authentication # JWT validation
4. Authorization # Policy enforcement
5. WebSockets # Raw WS support
6. SignalR Hubs # /subscribe, /chatMessage
7. CORS ("OpenCors") # Allow any origin/method/header
8. ErrorHandlerMiddleware # Global exception catching
9. Controllers # REST API routes
Global Error Handling
ErrorHandlerMiddleware catches unhandled exceptions, logs them via Serilog, and returns a sanitized problem-details response. No exception leaks to the client in production.
CORS Policy
options.AddPolicy("OpenCors", policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
Security Note: Review and restrict this policy for production deployments.
REST Endpoints
Controllers expose domain-oriented resource groups. Each controller delegates to an Application-layer service and returns DTOs. Key controller families:
| Domain | Controllers |
|---|---|
| Patients | PatientController, AdmissionController, DischargeController, PatientAppointmentController |
| Observations | ObservationsController, GroupedObservationsController, ConfigObservationController, AlarmController, SensorController |
| Devices | DeviceController, ProxyDeviceController, RelayController, LightBeaconController, CameraController, PumpsController, BoxController |
| Clinical | TreatmentsController, MedicinesController, DiagnosisController, PointOfCareController |
| System | UserController, UnitController, MasterListController, ServiceConfigController, DisplayController, ConfigDisplayController |
| Messaging | RabbitController, SendAlertController, NoticeController |
| Media | RecordingController, RecordingAlertController, QXController |
| Audit | AuditController, ApplicationController |
All endpoints require authentication ([Authorize] applied globally via a filter). Swagger UI lists available operations per environment.
WebSocket / SignalR Hubs
Hubs
| Hub | Route | Purpose |
|---|---|---|
UciHub |
/subscribe |
Real-time subscription channel for clients |
UciHub |
/chatMessage |
Bidirectional chat / notification channel |
WebSocket Options
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromSeconds(120)
};
app.UseWebSockets(webSocketOptions);
WebSocket Message Service
WebSocketMessageService implements IClientMessageService and handles pushing outbound messages to connected SignalR clients, decoupling domain events from transport concerns.
Swagger & OpenAPI
Swagger is enabled unconditionally:
app.UseSwagger();
app.UseSwaggerUI();
Customizations
- Newtonsoft.Json serializer registered globally (
ReferenceLoopHandling.Ignore,CamelCasePropertyNamesContractResolver,StringEnumConverter,ObjectIdConverter). - Schema IDs use fully qualified type names (
CustomSchemaIds(type => type.FullName)) to prevent collisions. ObjectIdmapping exposed asstringwithformat: objectid.
Access the UI at /swagger/index.html.
Serilog Bootstrap
Serilog is initialized from the Serilog configuration section with fallback to console-only:
builder.Host.UseSerilog((_, loggerConfig) =>
{
if (configuration.GetSection("Serilog").Exists())
{
loggerConfig.ReadFrom.Configuration(configuration, new() { SectionName = "Serilog" });
}
else
{
loggerConfig.MinimumLevel.Information().WriteTo.Console();
}
loggerConfig.Enrich.WithDynamicProperty(
"TraceIdentifier",
() => LogExecutionContext.TraceIdentifier);
});
Dynamic Trace Identifier
LogExecutionContext sets a per-request TraceIdentifier (GUID) that flows through all enrichers, enabling end-to-end log correlation across layers and modules.
Build & Run
From CLI
cd adas-core
dotnet run --launch-profile "LOCAL"
Available launch profiles (from Properties/launchSettings.json):
| Profile | HTTPS | HTTP | Binding |
|---|---|---|---|
LOCAL |
https://localhost:7006 |
http://localhost:5006 |
localhost |
HPAZ UCIP |
https://localhost:7006 |
http://localhost:5006 |
localhost |
HRYCM UCIP |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
H12O |
https://localhost:7006 |
http://localhost:5006 |
localhost |
HUVH-UCIN |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
CHUO |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
NursePlan |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
BombasBD |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
Auditoria |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
HUVH-UCIA |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
LocalTest |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
Develop |
https://0.0.0.0:7006 |
http://0.0.0.0:5006 |
all interfaces |
IIS Express |
IIS Express | — | http://localhost:60532 / SSL 44358 |
Docker |
Docker mapped | — | auto-assigned |
Docker
docker build -t adas-core:latest .
docker run -p 8080:80 -e ASPNETCORE_ENVIRONMENT=Production adas-core:latest
Design Rules
- Thin Controllers — Controllers must only validate input, invoke application services, and return DTOs. No business logic inside controllers.
- Global Authorization — The
[Authorize]filter is applied globally; anonymous endpoints must be explicitly opted out. - Configuration Over Code — Environment-specific behavior is driven by
appsettingsprofiles, not conditional compilation. - No Circular Dependencies — The Host references all layers but is never referenced by Domain or Application.
- Singleton vs Scoped — Repository registrations default to
Singletonfor stateless MongoDB access; scoped services are used only when per-request state is required (e.g.,PumpStateRepository). - Lazy Resolution — Heavy services are wrapped in
Lazy<T>to defer instantiation and reduce startup overhead. - Middleware Order Matters — Authentication must precede Authorization; WebSockets must precede SignalR hubs; ErrorHandler must wrap the Controller pipeline.
- Sensitive Data Protection — JWT secrets and database connection strings must use User Secrets or environment variables in production; never commit them to source control.
Back to adas-core Root README