Building distributed .NET applications means answering the same question every time: how do the parts talk to each other? REST needs hand-written HTTP clients and offers no compile-time safety. SignalR invokes methods by string name, which makes refactoring risky. gRPC brings type safety at the price of .proto files and a code-generation step. WCF had the right programming model and stayed behind on the legacy framework.
WitRPC takes the part worth keeping, the interface-driven contract, and builds it for modern .NET. Define a C# interface once and use it everywhere: on the server as the implementation contract, on the client as the proxy.
The model in thirty seconds
A service contract is a plain interface, events included:
public interface IChatService
{
Task SendMessage(string user, string message);
Task<List<string>> GetActiveUsers();
event Action<string, string> MessageReceived;
}The client obtains a proxy and calls it like a local object, with IntelliSense, refactoring, and type checking intact:
var chatService = client.GetService<IChatService>();
await chatService.SendMessage("Alice", "Hello, everyone!");
var users = await chatService.GetActiveUsers();
chatService.MessageReceived += (user, message) =>
Console.WriteLine($"{user}: {message}");When the server raises MessageReceived, every subscribed client gets it in real time. Communication is full-duplex over one connection: no polling, no separate push channel.
Around this core, the framework stays configurable in every direction. Transports range from memory-mapped files and named pipes for local IPC to TCP and WebSockets for the network, with REST for non-.NET callers. Serializers cover JSON, MessagePack, MemoryPack, and ProtoBuf, switchable in one line. Security is built in: RSA/AES encryption and token authorization on both sides of the handshake.
var server = WitServerBuilder.Build(options =>
{
options.WithService(new ChatService());
options.WithWebSocket("http://localhost:5000", maxClients: 100);
options.WithMessagePack();
options.WithEncryption();
options.WithAccessToken("your-secret-token");
});
server.StartWaitingForConnection();What's new in 2.3
Composite services. One server now hosts several service interfaces at once. Clients connect once, authenticate once, and request a typed proxy for any registered interface over the same connection:
options.WithServices()
.AddService<IUserService>(new UserService())
.AddService<IOrderService>(new OrderService())
.AddService<INotificationService>(new NotificationService())
.Build();Dependency injection. New DependencyInjection packages integrate WitRPC with ASP.NET Core: named servers and clients registered in the container, service implementations resolved from DI, auto-start and auto-connect tied to the host lifecycle, and remote proxies injectable into controllers like any other dependency.
Resilience. Clients survive real networks out of the box: WithAutoReconnect() restores dropped connections with exponential backoff, WithRetryPolicy() repeats calls that failed with transient errors, and lifecycle callbacks let the application refresh state after an interruption.
Health checks. The HealthChecks package plugs named WitRPC clients into standard ASP.NET Core health endpoints, so connection state shows up in existing monitoring alongside databases and queues.
Cross-platform encryption. New BouncyCastle packages implement the same RSA/AES scheme in pure C#, which makes encrypted WitRPC work where OS cryptography is unavailable, Blazor WebAssembly first among them: WithBouncyCastleEncryption() on both sides is the whole setup.
Performance
WitRPC's transport range shows up directly in measurements. In local IPC benchmarks (10 MB payloads, averages over 50 runs), memory-mapped files with MemoryPack completed one-way transfers in 15.6 ms and named pipes in 16.7 ms, ahead of every other framework configuration tested on the same machine. In remote benchmarks between Israel and Germany (1 MB payloads), WitRPC posted the best times among WitRPC, SignalR, gRPC, and CoreWCF.
The full methodology, raw numbers, and the open-source benchmark suite are in Comparing RPC Frameworks in .NET Applications; the benchmarks themselves live in the repository, ready to run on your own hardware.
Getting started
# Server
dotnet add package OutWit.Communication.Server.WebSocket
# Client
dotnet add package OutWit.Communication.Client.WebSocketThe Quick Start builds a working client-server pair in a few minutes, and the guides cover transports, security, composite services, resilience, and Blazor in depth. The source is on GitHub under Apache 2.0.
WitRPC has been in production use for a while; 2.3 is the release where the ecosystem around the core (hosting, resilience, browser support) caught up with the communication model itself. If you build .NET systems that talk to each other, give it a try.