AnyProtocol.Protocol.Grpc.AspNetCore
1.0.9
dotnet add package AnyProtocol.Protocol.Grpc.AspNetCore --version 1.0.9
NuGet\Install-Package AnyProtocol.Protocol.Grpc.AspNetCore -Version 1.0.9
<PackageReference Include="AnyProtocol.Protocol.Grpc.AspNetCore" Version="1.0.9" />
<PackageVersion Include="AnyProtocol.Protocol.Grpc.AspNetCore" Version="1.0.9" />
<PackageReference Include="AnyProtocol.Protocol.Grpc.AspNetCore" />
paket add AnyProtocol.Protocol.Grpc.AspNetCore --version 1.0.9
#r "nuget: AnyProtocol.Protocol.Grpc.AspNetCore, 1.0.9"
#:package AnyProtocol.Protocol.Grpc.AspNetCore@1.0.9
#addin nuget:?package=AnyProtocol.Protocol.Grpc.AspNetCore&version=1.0.9
#tool nuget:?package=AnyProtocol.Protocol.Grpc.AspNetCore&version=1.0.9
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="docs/assets/AnyProtocol_logo_dark.svg"> <source media="(prefers-color-scheme: light)" srcset="docs/assets/AnyProtocol_logo_light.svg"> <img alt="AnyProtocol" src="docs/assets/AnyProtocol_logo_dark.svg" width="420"> </picture> </p>
AnyProtocol
AnyProtocol is a .NET contract-first messaging library. A single interface can be registered as a local service or carried over REST, gRPC, Kafka, RabbitMQ, or ZeroMQ, with optional MCP tool exposure, request/reply, events, generated proxies, transport validation, health checks, and built-in diagnostics.
One logical server registration can be exposed through several protocols at the same time. Each client selects one protocol in its own configuration; neither the contract nor the service implementation contains transport-specific code.
Support: Core, abstraction, serializer, encoder, and InMemory packages target .NET 8 and .NET 10; see the support policy. The public API is still evolving. Pin package versions, validate transport semantics for your workload, and use the source generator plus serializer metadata before Native AOT deployment. Transport support is intentionally capability-based; a feature listed for one transport is not implied for the others.
Transport matrix
| Transport | Request/reply | Events/pub-sub | Streaming | Delivery | Durability | Ordering |
|---|---|---|---|---|---|---|
| InMemory | Emulated | Yes | Emulated | At most once | Volatile | Per channel |
| REST | Native | No | No | At most once | Volatile | None |
| gRPC | Native | No | Native server streaming | At most once | Volatile | None |
| Kafka | Emulated | Yes | Emulated | At least once | Durable | Per partition |
| RabbitMQ | Emulated | Yes | Emulated | At least once | Durable | Per channel¹ |
| ZeroMQ | Emulated | Yes | Emulated | At most once | Volatile | Per channel |
¹ Per-channel ordering requires one active consumer/handler for the queue; concurrent handlers can complete out of order.
MCP is an opt-in server exposure protocol rather than a client transport; tool calls have no independent delivery, durability, or ordering guarantee in this matrix.
See transport semantics before choosing a production transport.
Prerequisites
- .NET SDK
10.0.300or a compatible newer feature band - A Kafka broker for Kafka transport
- A RabbitMQ broker for RabbitMQ transport
- Reachable TCP endpoints for ZeroMQ
- ASP.NET Core hosting for REST or gRPC servers
From source:
git clone https://github.com/MCKanpolat/AnyProtocol.git
cd AnyProtocol
dotnet restore AnyProtocol.slnx
For an application using Microsoft DI and the local transport:
dotnet add package AnyProtocol.DependencyInjection.Microsoft
dotnet add package AnyProtocol.Protocol.InMemory
dotnet add package AnyProtocol.Serializer.TextJson
Package map
| Purpose | Package |
|---|---|
| Contracts, schema registry, and core pipeline | AnyProtocol, AnyProtocol.Abstraction |
| Microsoft DI and hosted lifecycle | AnyProtocol.DependencyInjection.Microsoft |
| Payload serialization (JSON / MessagePack) | AnyProtocol.Serializer.TextJson, AnyProtocol.Serializer.MessagePack |
| Envelope codecs (MessagePack / Protobuf / compression) | AnyProtocol.Encoder.MessagePack, AnyProtocol.Encoder.Protobuf, AnyProtocol.Encoder.Compression |
| Logging abstraction and Microsoft logging adapter | AnyProtocol.Logging.Abstraction, AnyProtocol.Logging.Microsoft |
| Optional ULID message IDs | AnyProtocol.MessageIdGenerator.Ulid |
| In-process transport | AnyProtocol.Protocol.InMemory |
| REST client / ASP.NET Core server | AnyProtocol.Protocol.Rest, AnyProtocol.Protocol.Rest.AspNetCore |
| gRPC client / ASP.NET Core server | AnyProtocol.Protocol.Grpc, AnyProtocol.Protocol.Grpc.AspNetCore |
| Kafka / RabbitMQ / ZeroMQ | AnyProtocol.Protocol.Kafka, AnyProtocol.Protocol.RabbitMq, AnyProtocol.Protocol.ZeroMq |
| Optional MCP exposure | AnyProtocol.Mcp, AnyProtocol.Mcp.AspNetCore |
| Large payload contract / Redis provider | AnyProtocol.Storage.Abstraction, AnyProtocol.Storage.Redis |
| Compile-time contract generation | AnyProtocol.Generator |
Schema contracts plus the built-in InMemorySchemaRegistry/JsonSchemaCompatibilityChecker are
shipped in the core packages. The registry is caller-managed: no durable external registry
provider is bundled, so production applications can supply their own adapter. Large payload
offload is an optional, provider-neutral feature; see the large payload guide.
It is disabled by default.
Envelope codecs
Payload serialization and transport envelope encoding are independent choices:
application message -> IMessageSerializer -> TransportEnvelope -> IEnvelopeCodec -> transport frame
gRPC and ZeroMQ use the backwards-compatible BinaryEnvelopeCodec by default. Both transports also accept an IEnvelopeCodec, so MessagePack or Protobuf framing can be selected and compression can decorate any base codec. Sender and receiver must use compatible codec configurations.
IEnvelopeCodec codec = new CompressedEnvelopeCodec(
new ProtobufEnvelopeCodec(),
new CompressedEnvelopeCodecOptions
{
Algorithm = CompressionAlgorithm.Brotli
});
var grpc = new GrpcMessagingProtocol(
channel,
codec,
disposeChannel: true);
var zeroMq = new ZeroMqMessagingProtocol(options, codec);
// ASP.NET Core gRPC server:
builder.Services.AddSingleton<IEnvelopeCodec>(codec);
builder.Services.AddAnyProtocolGrpc();
See the envelope codec guide for package selection, wire contracts, limits, and transport configuration.
Minimal request/reply
using AnyProtocol.Abstraction;
using AnyProtocol.DependencyInjection.Microsoft;
using AnyProtocol.Protocol.InMemory;
using AnyProtocol.Serializer.TextJson;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddAnyProtocol(link => link
.UseSerializer(new TextJsonMessageSerializer())
.AddTransport("default", new InMemoryMessagingProtocol())
.AddClient<IOrders>()
.AddServer<IOrders, Orders>());
using var host = builder.Build();
await host.StartAsync();
var client = host.Services.GetRequiredService<IOrders>();
var result = await client.GetAsync(new GetOrder("42"), CancellationToken.None);
Console.WriteLine(result.Status);
await host.StopAsync();
[Channel("orders")]
public interface IOrders
{
[Idempotent]
ValueTask<Order> GetAsync(GetOrder request, CancellationToken cancellationToken);
}
public sealed record GetOrder(string Id);
public sealed record Order(string Id, string Status);
public sealed class Orders : IOrders
{
public ValueTask<Order> GetAsync(GetOrder request, CancellationToken cancellationToken)
=> ValueTask.FromResult(new Order(request.Id, "ready"));
}
One service, multiple protocols
Use the built-in ProtocolKey values for compile-time-friendly configuration. Custom keys remain available for third-party protocols or named instances used by different registrations.
link.AddRestServer(ProtocolKey.Rest)
.AddGrpcServer(ProtocolKey.Grpc)
.AddServer<IOrders, Orders>(server => server.UseProtocols(
ProtocolKey.Rest,
ProtocolKey.Grpc,
ProtocolKey.Mcp));
The host maps each selected endpoint once:
services.AddAnyProtocolRest();
services.AddAnyProtocolGrpc();
services.AddAnyProtocolMcp();
app.MapAnyProtocol();
app.MapAnyProtocolGrpc();
app.MapAnyProtocolMcp();
A gRPC client and a REST client keep the same IOrders contract but choose independently:
link.AddClient<IOrders>(client => client.UseProtocol(ProtocolKey.Grpc));
// In another application:
link.AddClient<IOrders>(client => client.UseProtocol(ProtocolKey.Rest));
The choice can come from deployment configuration without changing the contract registration:
services.AddAnyProtocol(
configuration.GetSection("AnyProtocol"),
link => link.AddClient<IOrders>("OrdersClient"));
{
"AnyProtocol": {
"Clients": {
"OrdersClient": { "Protocol": "Grpc" }
}
}
}
Every selected protocol is validated against every contract operation during startup. An incompatible selection fails configuration instead of exposing a partial service. Duplicate native REST/gRPC bindings for one contract are rejected. MCP publishes only methods marked with [McpTool]; selecting MCP without registering and hosting its adapter stops application startup.
[Idempotent] permits configured retries; it does not provide deduplication.
Documentation and samples
- Getting started and transport switching
- Configuration reference
- Envelope codecs
- Large payload offload
- RabbitMQ guide
- Transport semantics
- Performance methodology
- Deployment
- Observability
- Security
- Metadata generation allowlist
- Transport development
- Support policy
- Architecture
- API reference
- OrderSystem multi-protocol reference
- OrderSystem MCP/REST host
- Native AOT smoke sample
Run the samples with:
dotnet run --project samples/OrderSystem.McpHost
dotnet run --project samples/OrderSystem.McpHost -- --stdio
dotnet run --project samples/AnyProtocol.AotSample
dotnet run --project samples/OrderSystem.MultiProtocol/OrderSystem.Server
dotnet run --project samples/OrderSystem.MultiProtocol/OrderSystem.Client -- --protocol Rest
dotnet run --project samples/OrderSystem.MultiProtocol/OrderSystem.Client -- --protocol Grpc
The multi-protocol order server uses http://localhost:5080 for REST/MCP and http://localhost:5081 for gRPC.
License
AnyProtocol is licensed under LGPL-3.0-or-later. Applications may link to the AnyProtocol libraries under their own license terms. Distributed changes to the AnyProtocol libraries themselves must remain available under LGPL-3.0-or-later with their corresponding source code.
The AnyProtocol name and logo are governed separately by the trademark policy. Forks must not present themselves as the official AnyProtocol project.
| 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
- AnyProtocol.DependencyInjection.Microsoft (>= 1.0.9)
- AnyProtocol.Protocol.Grpc (>= 1.0.9)
- CommunityToolkit.Diagnostics (>= 8.4.2)
- CommunityToolkit.HighPerformance (>= 8.4.2)
- Grpc.AspNetCore.Server (>= 2.83.0)
- Grpc.Net.Client (>= 2.83.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.11)
- Microsoft.Extensions.DependencyInjection (>= 10.0.11)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.11)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.11)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
See the GitHub release notes for the changes included in this version.