ContextR.Resolution
1.0.0-rc.1
See the version list below for details.
dotnet add package ContextR.Resolution --version 1.0.0-rc.1
NuGet\Install-Package ContextR.Resolution -Version 1.0.0-rc.1
<PackageReference Include="ContextR.Resolution" Version="1.0.0-rc.1" />
<PackageVersion Include="ContextR.Resolution" Version="1.0.0-rc.1" />
<PackageReference Include="ContextR.Resolution" />
paket add ContextR.Resolution --version 1.0.0-rc.1
#r "nuget: ContextR.Resolution, 1.0.0-rc.1"
#:package ContextR.Resolution@1.0.0-rc.1
#addin nuget:?package=ContextR.Resolution&version=1.0.0-rc.1&prerelease
#tool nuget:?package=ContextR.Resolution&version=1.0.0-rc.1&prerelease
ContextR
Context propagation for distributed .NET systems without brittle glue code.
ContextR helps you move request, tenant, user, and operational metadata across async boundaries, HTTP, and gRPC in a consistent and testable way.
Why This Project Was Born
We run a gateway + microservices architecture where authenticated requests are transformed into typed UserContext data (TenantId, UserId, and related fields).
That context must continue across HTTP, gRPC, and distributed events as services call each other.
Without a unified model, context handling leaks into business code and turns into repeated boilerplate that is easy to get wrong.
ContextR was created so engineers do not need to think about propagation mechanics in daily feature work.
Read the full story:
What You Get
- Snapshot-first model for safer async/background propagation
- Property mapping DSL for HTTP/gRPC keys
- Optional required/optional property contracts
- Payload strategies for complex types (
InlineJson,Chunking, token-ready) - Domain-aware failure hooks and runtime oversize strategy policy
- Dedicated transport packages for ASP.NET Core,
HttpClient, and gRPC
When To Use ContextR
Use ContextR when you need:
- consistent context propagation across service boundaries
- multi-tenant or user/correlation context continuity
- clean separation from
HttpContextin business logic - explicit behavior for oversize payloads and parse failures
Avoid ContextR for single-process apps that do not cross async/transport boundaries.
60-Second Quick Start
Install:
dotnet add package ContextR
dotnet add package ContextR.Propagation
dotnet add package ContextR.Propagation.Mapping
dotnet add package ContextR.Hosting.AspNetCore
dotnet add package ContextR.Transport.Http
Register:
builder.Services.AddContextR(ctx =>
{
ctx.Add<UserContext>(reg => reg
.MapProperty(c => c.TraceId, "X-Trace-Id")
.MapProperty(c => c.TenantId, "X-Tenant-Id")
.MapProperty(c => c.UserId, "X-User-Id")
.UseAspNetCore()
.UseGlobalHttpPropagation());
});
public sealed class UserContext
{
public string? TraceId { get; set; }
public string? TenantId { get; set; }
public string? UserId { get; set; }
}
Result:
- incoming middleware extracts request headers into context
- outgoing
HttpClientcalls automatically inject mapped headers - your app code reads context from ContextR abstractions, not transport APIs
Core Interfaces: Why Both Exist
Engineers often ask why ContextR has both IContextAccessor and IContextSnapshot.
IContextAccessor (singleton, live view)
- Reads current ambient value from
AsyncLocalon every call - Reflects the value that is active right now (middleware writes,
BeginScope()overrides, cleanup restores/clears) - Used by integration plumbing that runs at execution time (
HttpClienthandlers, gRPC interceptors, middleware)
Why singleton?
IContextAccessor is stateless. It does not store request data in the instance; it only reads from ambient AsyncLocal state. A singleton accessor is safe and lets long-lived infrastructure components read the live context consistently.
IContextSnapshot (scoped, stable view)
- Captures context once for a scope (typically request scope)
- Immutable view for business/application code
- Safe to pass to background work and later re-activate with
BeginScope()
Why snapshot cannot replace accessor everywhere
Outbound propagation components need the currently active ambient context at the exact moment they run.
BeginScope() works by writing snapshot values into AsyncLocal; handlers then read through IContextAccessor.
If handlers depended only on snapshots, they would not know which snapshot should be active in concurrent scenarios (for example parallel Task.Run/batch work where multiple snapshots can exist).
Practical rule:
- business logic: prefer
IContextSnapshot - infrastructure/integration pipeline: use
IContextAccessor
Marketing Message (Site Hero Candidate)
Build once. Propagate everywhere.
ContextR makes context flow reliable across async code, HTTP, gRPC, and background processing without turning your codebase into header plumbing.
Documentation Hub
- Getting Started
- Usage Cookbook
- Q&A / FAQ
- Architecture
- Context Resolution
- Propagation Mapping
- Inline JSON Strategy
- Chunking Strategy
- Token Strategy Contracts
- ASP.NET Core Transport
- HTTP Client Transport
- HTTP Client Handler Scope Deep Dive
- gRPC Transport
GitHub Pages Docs
Once GitHub Pages is enabled for this repository, the site will be published at:
https://arttonoyan.github.io/ContextR/
Local docs preview:
python -m pip install --upgrade pip
pip install "mkdocs<2" "mkdocs-material<10" pymdown-extensions
mkdocs serve
Production build check:
mkdocs build --strict
Samples
Real-world examples are available under samples:
- Multi-tenant SaaS propagation
- Mixed HTTP + gRPC microservices
- Background jobs propagation
- Gateway ingress resolution (JWT → UserContext)
- Replacing
IHttpContextAccessorusage with snapshot model - JWT vs operational context propagation
Package Map
| Package | Purpose |
|---|---|
ContextR |
Core ambient context, snapshots, scopes, domains |
ContextR.Resolution |
Ingress context resolution contracts/orchestrator/policies (optional package) |
ContextR.Propagation |
Propagation contracts + registration APIs |
ContextR.Propagation.Mapping |
MapProperty and advanced Map(...) DSL |
ContextR.Propagation.InlineJson |
JSON serializer strategy for complex properties |
ContextR.Propagation.Chunking |
Chunk split/reassembly for oversize payloads |
ContextR.Propagation.Token |
Token/reference propagation contracts |
ContextR.Hosting.AspNetCore |
Incoming ASP.NET Core extraction middleware |
ContextR.Transport.Http |
Outgoing HttpClient propagation handler |
ContextR.Transport.Grpc |
gRPC client/server propagation interceptors |
Resolution Registration Note
ContextR.Resolution stays optional by design.
If you use UseResolver(...) or UseResolutionPolicy(...), resolution services are auto-registered for you.
Use AddContextRResolution() only for advanced cases where you need orchestrator/policy services without configuring resolver/policy registrations yet.
Design Principles
- explicit over implicit behavior
- transport-agnostic core, transport-specific extensions
- safe defaults with configurable policy where needed
- testable abstractions first (domain and execution-scope aware)
Status
ContextR is actively evolving. Breaking changes may occur while architecture and package boundaries are refined.
| 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
- ContextR (>= 1.0.0-rc.1)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.3)
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.1.0 | 67 | 3/27/2026 |
| 1.0.0 | 91 | 3/11/2026 |
| 1.0.0-rc.5 | 46 | 3/11/2026 |
| 1.0.0-rc.4 | 42 | 3/5/2026 |
| 1.0.0-rc.3 | 48 | 3/4/2026 |
| 1.0.0-rc.2 | 43 | 3/3/2026 |
| 1.0.0-rc.1 | 43 | 3/3/2026 |