SyntaxCircus.AspNetCore.Common 0.1.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package SyntaxCircus.AspNetCore.Common --version 0.1.3
                    
NuGet\Install-Package SyntaxCircus.AspNetCore.Common -Version 0.1.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SyntaxCircus.AspNetCore.Common" Version="0.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SyntaxCircus.AspNetCore.Common" Version="0.1.3" />
                    
Directory.Packages.props
<PackageReference Include="SyntaxCircus.AspNetCore.Common" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SyntaxCircus.AspNetCore.Common --version 0.1.3
                    
#r "nuget: SyntaxCircus.AspNetCore.Common, 0.1.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SyntaxCircus.AspNetCore.Common@0.1.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SyntaxCircus.AspNetCore.Common&version=0.1.3
                    
Install as a Cake Addin
#tool nuget:?package=SyntaxCircus.AspNetCore.Common&version=0.1.3
                    
Install as a Cake Tool

SyntaxCircus.AspNetCore.Common

Build NuGet License: MIT

The small pieces of ASP.NET Core host boilerplate that show up in nearly every project, in one place: correlation-ID middleware, security headers, a composable exception-handler/HSTS bootstrap, RFC 7807 ProblemDetails exception handling, trusted-proxy validation, standard health check endpoints, and rate-limiting policy helpers.

No support guaranteed. Published as-is and maintained on a best-effort basis. Issues and PRs are welcome, but there's no SLA — fork it or vendor what you need if that's not enough.

Correlation ID

builder.Services.AddCorrelationId(); // optionally: options => options.HeaderName = "X-My-Correlation-Id"

var app = builder.Build();
app.UseCorrelationId();

Reads (or generates) a correlation ID per request, echoes it on the response header, tags the current Activity, and pushes it — with the current trace/span ID — into the logger scope for the rest of the request, so downstream log lines carry it automatically. SyntaxCircus.AspNetCore.Common.CorrelationContextAccessor.CurrentCorrelationId gives ambient (AsyncLocal) access to it outside the middleware pipeline.

Security headers

builder.Services.AddSecurityHeaders(builder.Configuration); // binds the "SecurityHeaders" section

var app = builder.Build();
app.UseSecurityHeaders();

Sets Referrer-Policy, X-Frame-Options, X-Content-Type-Options, Permissions-Policy, Content-Security-Policy, and Strict-Transport-Security from SecurityHeadersOptions, with sensible defaults you can override per-key in configuration.

Exception handling / HSTS bootstrap

var app = builder.Build();
app.UseStandardExceptionHandling(); // "/error", HSTS — skipped entirely in Development

Bundles UseExceptionHandler(errorPath) + UseHsts(), both skipped in Development, with an optional status-code re-execute page (useStatusCodePages: true). It's a plain extension method, not something wired in automatically — a pure API host behind a reverse proxy that already terminates TLS and handles error pages doesn't need to call it.

ProblemDetails exception handling

builder.Services.AddProblemDetailsExceptionHandling(options =>
{
    options.BaseTypeUri = "https://errors.example.com";
    options.ExceptionMapper = ex => ex switch
    {
        NotFoundException => new ProblemMapping(StatusCodes.Status404NotFound, "not-found"),
        _ => new ProblemMapping(StatusCodes.Status500InternalServerError, "internal-error"),
    };
});

var app = builder.Build();
app.UseProblemDetailsExceptionHandling();

Catches unhandled exceptions and writes an RFC 7807 ProblemDetails response, with Type built from BaseTypeUri + your error code. Which exception types mean what status/code is deliberately a delegate you supply — that mapping is product-specific and the package doesn't try to guess it for you. A reasonable default mapper is provided if you don't set one, and it never puts a raw ex.Message into the response body: every case — including the unmapped/500 fallback — gets an explicit, generic Detail string. This matters because ex.Message on an exception nobody anticipated (a database error, a file path, connection details) can carry internals that shouldn't reach an API client.

The same rule applies to custom mappers: if your ExceptionMapper leaves a ProblemMapping's Detail unset (null), the middleware leaves Detail null in the response too — it does not silently substitute ex.Message. If you want the old fall-back-to-ex.Message behavior for cases your mapper doesn't set Detail for, opt in explicitly:

builder.Services.AddProblemDetailsExceptionHandling(options =>
{
    options.IncludeExceptionMessageInDetail = true; // restores ex.Message fallback when a mapping's Detail is null
});

IncludeExceptionMessageInDetail defaults to false. Only set it to true if you've verified your exception messages are safe to expose to API clients (e.g. gated to non-production environments).

Trusted-proxy validation

builder.Services.AddTrustedProxyForwardedHeaders(builder.Configuration); // binds the "TrustedProxy" section

var trustedProxyOptions = new TrustedProxyOptions();
builder.Configuration.GetSection(TrustedProxyOptions.SectionName).Bind(trustedProxyOptions);
builder.Environment.ValidateTrustedProxyConfiguration(trustedProxyOptions); // throws outside Development if misconfigured

var app = builder.Build();
app.UseForwardedHeaders();

Fails fast at startup if you're running behind a reverse proxy without telling ASP.NET Core which upstream hosts to actually trust — without TrustedProxies/TrustedNetworks configured, forwarded headers (X-Forwarded-For/-Proto) would otherwise be trusted from anyone.

Health checks

var app = builder.Build();
app.MapStandardHealthChecks(); // /health/live (no checks run) and /health/ready (checks tagged "ready")

Maps standard liveness/readiness endpoints rendered via HealthCheckResponseWriter (status, total duration, and per-check name/status/duration/description as JSON). Register your own IHealthCheck implementations with AddHealthChecks().AddCheck<T>(tags: ["ready"]) as usual — this just standardizes the endpoints and response shape.

Rate limiting

builder.Services.AddRateLimiter(options =>
{
    options.AddPerIpFixedWindow("public", permitLimit: 60, window: TimeSpan.FromMinutes(1));
    options.AddPerSubjectFixedWindow("authenticated", permitLimit: 600, window: TimeSpan.FromMinutes(1));
    options.UseProblemDetailsRejection();
});

var app = builder.Build();
app.UseRateLimiter();

API surface

Method Purpose
AddPerIpFixedWindow(policyName, permitLimit, window) Fixed-window policy partitioned by remote IP ("unknown" fallback).
AddPerIpFixedWindow(policyName, permitLimit, window, configure) Same as above, with per-policy FixedWindowRateLimiterOptions overrides.
AddPerSubjectFixedWindow(policyName, permitLimit, window) Fixed-window policy partitioned by authenticated subject (sub, fallback NameIdentifier, then remote IP).
AddPerSubjectFixedWindow(policyName, permitLimit, window, configure) Same as above, with per-policy FixedWindowRateLimiterOptions overrides.
AddPartitionedFixedWindow(policyName, partitionKeySelector, permitLimit, window, configure = null) Additive advanced API for custom partition key composition (route, claim combinations, tenant headers, etc.).
UseProblemDetailsRejection(errorCode = "rate-limited") Writes ProblemDetails 429 responses and includes Retry-After when available.

Advanced partition-key composition (additive, non-breaking)

builder.Services.AddRateLimiter(options =>
{
    options.AddPartitionedFixedWindow(
        "tenant-route",
        ctx => $"{ctx.User.FindFirst("tenant_id")?.Value ?? "anon"}:{ctx.Request.Path}",
        permitLimit: 120,
        window: TimeSpan.FromMinutes(1),
        configure: fixedWindow =>
        {
            fixedWindow.QueueLimit = 5;
            fixedWindow.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        });

    options.UseProblemDetailsRejection();
});

This keeps the existing convenience helpers intact while adding custom partition selection and optional per-policy overrides when app-level policy composition needs to be richer.

Contributing

Issues and pull requests are welcome:

  • Keep changes focused, with a clear description of the behavior change.
  • Match the existing code style (see .editorconfig).
  • Call out any breaking changes to the public API in your PR description.

License

MIT — see LICENSE.txt.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on SyntaxCircus.AspNetCore.Common:

Package Downloads
SyntaxCircus.AspNetCore.Common.MassTransit

Optional companion to SyntaxCircus.AspNetCore.Common: MassTransit consume/publish/send filters that propagate the configured correlation ID across message-bus boundaries, keeping log enrichment consistent with the HTTP middleware.

SyntaxCircus.Observability

Opt-in OpenTelemetry, Serilog OTLP, and Sentry-compatible error-reporting bootstrap for .NET server hosts.

SyntaxCircus.Blazor.Seo

SEO building blocks for Blazor Server marketing sites: a SeoHead component, typed Schema.org JSON-LD records, a canonical URL builder, and thin sitemap.xml/robots.txt wrappers over SyntaxCircus.AspNetCore.Common.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.12 84 9/7/2026
0.1.11 186 8/29/2026
0.1.10 105 8/28/2026
0.1.9 609 8/21/2026
0.1.8 109 8/21/2026
0.1.7 140 8/19/2026
0.1.6 114 8/18/2026
0.1.5 116 8/18/2026
0.1.4 111 8/18/2026
0.1.3 112 8/17/2026
0.1.2 119 8/17/2026
0.1.1 101 8/16/2026
0.1.0 108 8/16/2026