ContextR.Transport.Grpc¶
gRPC context propagation for ContextR. This package provides interceptors and helper extensions to propagate ambient context through gRPC metadata on the client side and extract it on the server side.
When to use this package¶
Use ContextR.Transport.Grpc when your services communicate over gRPC and you want typed context values (correlation IDs, tenant identifiers, feature flags) to flow automatically between caller and callee.
Install¶
Dependencies: ContextR (core), ContextR.Propagation (for IContextPropagator<T>), Grpc.Core.Api, Grpc.Net.ClientFactory.
Client-side propagation¶
Global propagation (all gRPC clients)¶
Apply ContextR propagation to all gRPC clients registered via AddGrpcClient:
builder.Services.AddContextR(ctx =>
{
ctx.Add<CorrelationContext>(reg => reg
.MapProperty(c => c.TraceId, "x-trace-id")
.UseGlobalGrpcPropagation());
});
UseGlobalGrpcPropagation() captures the registration domain (if any) and registers interceptor options through GrpcClientFactoryOptions.
Per-client propagation¶
Apply propagation only to a specific gRPC client:
builder.Services.AddContextR(ctx =>
{
ctx.Add<CorrelationContext>(reg => reg
.MapProperty(c => c.TraceId, "x-trace-id"));
});
builder.Services.AddGrpcClient<MyGrpcClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.AddContextRGrpcPropagation<CorrelationContext>();
AddContextRGrpcPropagation<T>() is an extension on IHttpClientBuilder.
Server-side extraction¶
ContextInterceptor<TContext> extracts gRPC metadata into a typed context object through IContextPropagator<TContext> and writes it to ambient storage via IContextWriter.
Register it as a gRPC server interceptor:
builder.Services.AddContextR(ctx =>
{
ctx.Add<CorrelationContext>(reg => reg
.MapProperty(c => c.TraceId, "x-trace-id"));
});
builder.Services.AddTransient<ContextInterceptor<CorrelationContext>>();
builder.Services.AddGrpc(options =>
{
options.Interceptors.Add<ContextInterceptor<CorrelationContext>>();
});
After that, gRPC handlers can read ambient values with IContextAccessor / IContextSnapshot.
Domain-aware behavior¶
When configured in a domain, interceptors are domain-aware:
builder.Services.AddContextR(ctx =>
{
ctx.Add<CorrelationContext>()
.AddDomain("grpc", d => d.Add<CorrelationContext>(reg => reg
.MapProperty(c => c.TraceId, "x-trace-id")
.UseGlobalGrpcPropagation()));
});
In this case, client propagation reads from _accessor.GetContext<TContext>("grpc") rather than the default slot.
Metadata key handling¶
gRPC metadata keys are treated as lowercase in transport helpers. ContextR gRPC adapters normalize keys to lowercase before read/write to keep behavior consistent with gRPC conventions.
Complex payloads and metadata limits¶
For mapped complex properties, configure a payload strategy explicitly:
ctx.Add<UserContext>(reg => reg
.UseInlineJsonPayloads<UserContext>(o =>
{
o.MaxPayloadBytes = 4096;
o.OversizeBehavior = ContextOversizeBehavior.FailFast;
})
.MapProperty(c => c.Roles, "x-roles")
.UseGlobalGrpcPropagation());
gRPC metadata is still header-based and constrained by transport/proxy limits. Keep inline payloads bounded and prefer token/reference strategy for large values.
File map¶
| File | Role |
|---|---|
ContextPropagationInterceptor.cs |
Client interceptor that injects context into outgoing metadata |
ContextInterceptor.cs |
Server interceptor that extracts metadata and writes ambient context |
GrpcMetadataContextPropagatorExtensions.cs |
Metadata adapter helpers for IContextPropagator<T> |
Extensions/ContextRGrpcRegistrationExtensions.cs |
UseGlobalGrpcPropagation() on IContextRegistrationBuilder<T> |
Extensions/ContextRGrpcClientBuilderExtensions.cs |
Per-client gRPC extensions on IHttpClientBuilder / GrpcClientFactoryOptions |