Dosaic.Hosting.WebHost
1.2.9
dotnet add package Dosaic.Hosting.WebHost --version 1.2.9
NuGet\Install-Package Dosaic.Hosting.WebHost -Version 1.2.9
<PackageReference Include="Dosaic.Hosting.WebHost" Version="1.2.9" />
<PackageVersion Include="Dosaic.Hosting.WebHost" Version="1.2.9" />
<PackageReference Include="Dosaic.Hosting.WebHost" />
paket add Dosaic.Hosting.WebHost --version 1.2.9
#r "nuget: Dosaic.Hosting.WebHost, 1.2.9"
#:package Dosaic.Hosting.WebHost@1.2.9
#addin nuget:?package=Dosaic.Hosting.WebHost&version=1.2.9
#tool nuget:?package=Dosaic.Hosting.WebHost&version=1.2.9
Dosaic.Hosting.WebHost
Dosaic.Hosting.WebHost is the core orchestration package for any Dosaic-based service. It wires together plugin discovery, dependency injection, middleware pipeline configuration, health checks, OpenTelemetry, structured logging, CORS, response compression, IP rate limiting, and endpoint routing — all driven by the plugin interfaces from Dosaic.Hosting.Abstractions.
This package is mandatory. Without it no plugins can be loaded or configured.
Installation
dotnet add package Dosaic.Hosting.Generator # required for AOT-compatible plugin discovery
dotnet add package Dosaic.Hosting.WebHost
Or as package references in your .csproj:
<PackageReference Include="Dosaic.Hosting.Generator" Version="" />
<PackageReference Include="Dosaic.Hosting.WebHost" Version="" />
Usage
Replace the content of Program.cs with:
using Dosaic.Hosting.WebHost;
PluginWebHostBuilder.RunDefault(Dosaic.Generated.DosaicPluginTypes.All);
DosaicPluginTypes.All is a Type[] emitted at compile time by Dosaic.Hosting.Generator — no runtime reflection scanning is required.
For advanced scenarios (e.g. integration testing) you can separate build from run:
using Dosaic.Hosting.WebHost;
var host = PluginWebHostBuilder.Create(Dosaic.Generated.DosaicPluginTypes.All, args).Build();
host.Run();
Features
| Feature | Details |
|---|---|
| AOT-compatible plugin discovery | Plugin types resolved from source-generated Type[] — no reflection at runtime |
| Structured logging | Serilog with span/thread enrichers, structured request logging |
| OpenTelemetry | Metrics, tracing (OTLP), and logging exporters; Prometheus scraping endpoint at /metrics |
| Health checks | Built-in liveness checks (API, disk, memory); plugin and attribute-driven registrations |
| CORS | Configurable policy via CorsPolicy config section |
| Response compression | Brotli + Gzip (fastest level), applied to HTTP and HTTPS |
| IP rate limiting | AspNetCoreRateLimit integration, configurable via ipRateLimiting section |
| Layered configuration | JSON, YAML, secrets files, env vars, CLI args — ordered by specificity |
| YAML input/output formatters | Controllers accept and return application/yaml in addition to JSON |
| Forwarded headers | All forwarded headers trusted (proxy-friendly) |
| Configurable Kestrel | Listening URLs and max request body size controlled via config |
Plugin Lifecycle
PluginWebHostBuilder.Build() executes the following phases in order:
1 — Host Configuration (HostConfigurator)
- Clears default configuration sources and rebuilds them in the defined loading order (see Configuration below)
- Configures Kestrel: listening URLs (
host:urls), max request body size (host:maxRequestSize), server header suppression - Bootstraps Serilog structured logging
2 — Service Configuration (ServiceConfigurator)
- Registers default services: JSON serialization, memory cache, datetime providers, forwarded headers
- Configures CORS, response compression, IP rate limiting
- Adds MVC controllers with YAML formatters and custom validation error responses
- Discovers and registers
[Configuration(...)]-attributed classes fromIConfiguration - Registers health checks: built-in liveness checks +
[HealthCheck]-attributed types + plugin-contributed checks - Configures OpenTelemetry metrics, tracing, and logging
- Calls
IPluginServiceConfiguration.ConfigureServices()on all discovered plugins (sorted by origin)
3 — App Build
WebApplicationBuilder.Build() finalises the DI container.
4 — Application Configuration (AppConfigurator)
- Enables forwarded headers, response compression, IP rate limiting, CORS, Prometheus endpoint, routing
- Registers
[Middleware]-attributed types ordered by theirOrderproperty - Calls
IPluginApplicationConfiguration.ConfigureApplication()on all discovered plugins - Maps health endpoints (
/health/liveness,/health/readiness) - Maps controllers
- Calls
IPluginEndpointsConfiguration.ConfigureEndpoints()on all discovered plugins
5 — Instance Cleanup
TypeImplementationResolver.ClearInstances() disposes all plugin constructor instances created during build.
Plugin Sort Order
| Plugin origin | Sort key | Runs |
|---|---|---|
Dosaic.* namespace |
sbyte.MinValue |
First |
| Third-party plugins | 0 |
Middle |
| Host assembly plugins | sbyte.MaxValue |
Last |
Configuration
Kestrel / Host
host:
urls: "http://+:8080" # default; separate multiple URLs with ","
maxRequestSize: 8388608 # default 8 MB
Environment variables (single _ maps to : hierarchy):
HOST_URLS=http://+:8080
HOST_MAXREQUESTSIZE=8388608
Configuration File Loading Order
Dosaic loads configuration in the following order (later sources override earlier ones):
appsettings.jsonappsettings.yaml/appsettings.ymlappsettings.*.jsonappsettings.*.yaml/appsettings.*.ymlappsettings.secrets.json/appsettings.secrets.yaml/appsettings.secrets.ymlappsettings.*.secrets.json/appsettings.*.secrets.yaml/appsettings.*.secrets.yml- Environment variables
- Command-line arguments
Files are sorted by node count (number of .-separated segments) within each group. Secrets files always load after non-secrets files. Files whose names do not start with appsettings are ignored.
Additional Config Paths
You can load configuration files from additional directories. Those files are loaded before the main application directory.
Via environment variable:
HOST_ADDITIONALCONFIGPATHS=/path/to/configs,/another/path
Via command-line argument:
dotnet run --HOST:ADDITIONALCONFIGPATHS "/path/to/configs,/another/path"
- Subfolders are scanned recursively for
appsettings.*files - Supports
.json,.yaml,.ymlformats - Non-existent paths raise a
DirectoryNotFoundException
Environment Variable Mapping
Dosaic uses a custom provider that maps environment variable names to configuration keys by replacing _ with : (hierarchy separator). Double underscore __ is first collapsed to single _ before the mapping.
HOST_URLS -> host:urls
SERILOG_minimumLevel -> serilog:minimumLevel
Logging (Serilog)
serilog:
minimumLevel: Information # Verbose | Debug | Information | Warning | Error | Fatal
override:
System: Error
Microsoft: Error
Environment variables:
SERILOG_minimumLevel=Information
SERILOG_OVERRIDE_SYSTEM=Error
SERILOG_OVERRIDE_MICROSOFT=Error
CORS
CorsPolicy:
origins:
- "https://example.com"
methods:
- "GET"
- "POST"
headers:
- "*"
exposedHeaders:
- "*"
If any of origins, methods, headers, or exposedHeaders are not specified, they default to ["*"].
IP Rate Limiting
ipRateLimiting:
enableEndpointRateLimiting: true
generalRules:
- endpoint: "*"
period: "1s"
limit: 50
ipRateLimitPolicies: {}
Refer to AspNetCoreRateLimit documentation for the full schema.
OpenTelemetry
When telemetry:host is configured, traces, metrics, and logs are exported via OTLP. Log messages are enriched with SpanId and TraceId.
telemetry:
host: http://localhost:4317 # OTLP endpoint
protocol: grpc # grpc | http/protobuf
headers:
- name: Authorization
value: "Bearer <token>"
Without telemetry:host, only the Prometheus scraping endpoint (/metrics) is active.
Metrics instrumentation (always active):
- ASP.NET Core request metrics
- HTTP client metrics
- .NET runtime metrics
- Process metrics
- All custom
ActivitySourcemeters (*)
Tracing instrumentation (requires telemetry:host):
- ASP.NET Core (Swagger paths excluded)
- HTTP client
- All custom
ActivitySourcesources (*) - B3 propagation (single and multi-header)
Health Endpoints
| Endpoint | Tags filtered |
|---|---|
GET /health/liveness |
liveness |
GET /health/readiness |
readiness |
Both endpoints return a JSON body:
{
"status": "Healthy",
"totalDuration": "00:00:00.012",
"entries": [
{
"name": "api",
"status": "Healthy",
"description": null,
"tags": ["liveness"],
"duration": "00:00:00.001",
"exceptionMessage": null
}
]
}
Built-in liveness checks registered automatically:
| Check | Description |
|---|---|
api |
Always healthy — confirms the process is running |
disk_space |
Checks free space on all drives |
memory |
Asserts allocated memory is below 2 GB |
Plugins can contribute additional checks via IPluginHealthChecksConfiguration.ConfigureHealthChecks().
Custom checks can also be auto-discovered by implementing IHealthCheck and annotating the class with [HealthCheck("name", ...tags)].
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- AspNetCore.HealthChecks.System (>= 9.0.0)
- AspNetCoreRateLimit (>= 5.0.0)
- Chronos.Net (>= 2.0.24)
- Dosaic.Hosting.Abstractions (>= 1.2.9)
- NetEscapades.Configuration.Yaml (>= 3.1.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.15.0)
- OpenTelemetry.Exporter.Prometheus.AspNetCore (>= 1.15.0-beta.1)
- OpenTelemetry.Extensions.Hosting (>= 1.15.0)
- OpenTelemetry.Extensions.Propagators (>= 1.15.0)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.15.0)
- OpenTelemetry.Instrumentation.Http (>= 1.15.0)
- OpenTelemetry.Instrumentation.Process (>= 1.15.0-beta.1)
- OpenTelemetry.Instrumentation.Runtime (>= 1.15.0)
- Serilog.AspNetCore (>= 10.0.0)
- Serilog.Enrichers.Span (>= 3.1.0)
- Serilog.Enrichers.Thread (>= 4.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.9 | 0 | 3/13/2026 |
| 1.2.8 | 40 | 3/9/2026 |
| 1.2.7 | 40 | 3/4/2026 |
| 1.2.6 | 68 | 2/19/2026 |
| 1.2.5 | 50 | 2/17/2026 |
| 1.2.4 | 79 | 2/13/2026 |
| 1.2.3 | 64 | 1/27/2026 |
| 1.2.2 | 257 | 12/16/2025 |
| 1.2.1 | 237 | 12/16/2025 |
| 1.2.0 | 391 | 12/11/2025 |
| 1.1.21 | 416 | 12/10/2025 |
| 1.1.20 | 387 | 11/18/2025 |
| 1.1.19 | 265 | 11/11/2025 |
| 1.1.18 | 171 | 10/14/2025 |
| 1.1.17 | 170 | 10/1/2025 |
| 1.1.16 | 179 | 9/25/2025 |
| 1.1.15 | 162 | 9/24/2025 |
| 1.1.14 | 163 | 9/24/2025 |
| 1.1.13 | 167 | 9/24/2025 |
| 1.1.12 | 300 | 9/16/2025 |