WitRPC is a modern API for client-server communication designed to simplify development and provide a robust, extensible framework. It offers a seamless way to handle real-time and event-driven interactions with minimal setup, acting as a powerful alternative to traditional frameworks like WCF and SignalR.
- Dynamic Proxy Mechanism: Client-side proxies mirror server interfaces, enabling natural interaction with server-side objects via method calls, property access, and event subscriptions.
- Multiple Transport Options:
- Memory-Mapped Files
- Named Pipes
- TCP (with TLS support)
- WebSocket
- REST
- Composite Services: Host multiple service interfaces on a single server, clients can request proxies for any registered interface.
- Security:
- End-to-end encryption (AES/RSA)
- Cross-platform BouncyCastle encryption (works in Blazor WebAssembly)
- Token-based authorization
- Serialization:
- JSON (default)
- MessagePack
- MemoryPack
- ProtoBuf
- Resilience:
- Auto-reconnection with configurable retry strategies
- Retry policies for failed calls
- Health Checks: Built-in health check support for ASP.NET Core applications
- Cross-Platform Support: Works across all .NET-supported platforms, including Blazor WebAssembly.
- Extensibility: Default implementations for serialization, encryption, and authorization can be replaced with custom ones.
| Package | Description | NuGet |
|---|---|---|
OutWit.Communication |
Core communication library | |
OutWit.Communication.Client |
Base client library | |
OutWit.Communication.Server |
Base server library |
Install the transport package you need. For example, for WebSocket:
# Server
dotnet add package OutWit.Communication.Server.WebSocket
# Client
dotnet add package OutWit.Communication.Client.WebSocketpublic interface IExampleService
{
event Action ProcessingStarted;
event Action<double> ProgressChanged;
event Action<string> ProcessingCompleted;
bool StartProcessing();
void StopProcessing();
Task<string> ProcessDataAsync(string data);
}public class ExampleService : IExampleService
{
public event Action ProcessingStarted = delegate { };
public event Action<double> ProgressChanged = delegate { };
public event Action<string> ProcessingCompleted = delegate { };
public bool StartProcessing()
{
ProcessingStarted();
return true;
}
public void StopProcessing() { }
public async Task<string> ProcessDataAsync(string data)
{
await Task.Delay(100);
return $"Processed: {data}";
}
}var server = WitServerBuilder.Build(options =>
{
options.WithService(new ExampleService());
options.WithWebSocket("http://localhost:5000", maxClients: 100);
options.WithJson();
options.WithEncryption();
options.WithAccessToken("your-secret-token");
});
server.StartWaitingForConnection();var client = WitClientBuilder.Build(options =>
{
options.WithWebSocket("ws://localhost:5000");
options.WithJson();
options.WithEncryption();
options.WithAccessToken("your-secret-token");
});
await client.ConnectAsync(TimeSpan.FromSeconds(5), CancellationToken.None);
var service = client.GetService<IExampleService>();
// Subscribe to events
service.ProcessingStarted += () => Console.WriteLine("Processing Started");
service.ProgressChanged += progress => Console.WriteLine($"Progress: {progress}%");
service.ProcessingCompleted += result => Console.WriteLine($"Completed: {result}");
// Call methods
service.StartProcessing();
var result = await service.ProcessDataAsync("Hello");Host multiple service interfaces on a single server:
// Server
var server = WitServerBuilder.Build(options =>
{
options.WithServices()
.AddService<IUserService>(new UserService())
.AddService<IOrderService>(new OrderService())
.AddService<INotificationService>(new NotificationService())
.Build();
options.WithTcp(5000, maxClients: 100);
options.WithJson();
});
// Client
var userService = client.GetService<IUserService>();
var orderService = client.GetService<IOrderService>();Use BouncyCastle encryption for Blazor WebAssembly clients:
// Client (Blazor WebAssembly)
var client = WitClientBuilder.Build(options =>
{
options.WithWebSocket("ws://server:5000");
options.WithJson();
options.WithBouncyCastleEncryption(); // Works in WASM!
});
// Server (must also use BouncyCastle)
var server = WitServerBuilder.Build(options =>
{
options.WithWebSocket("http://0.0.0.0:5000", maxClients: 100);
options.WithJson();
options.WithBouncyCastleEncryption();
options.WithService(myService);
});Enable automatic reconnection for resilient connections:
var client = WitClientBuilder.Build(options =>
{
options.WithTcp("localhost", 5000);
options.WithJson();
options.WithAutoReconnect(reconnect =>
{
reconnect.MaxAttempts = 5;
reconnect.InitialDelay = TimeSpan.FromSeconds(1);
reconnect.MaxDelay = TimeSpan.FromSeconds(30);
});
});For more detailed documentation, visit witrpc.io.
See CHANGELOG.md for a list of changes.
Licensed under the Apache License, Version 2.0. See LICENSE.
If you use WitRPC in a product, a mention is appreciated (but not required), for example: "Powered by WitRPC (https://witrpc.io/)".
"WitRPC" and the WitRPC logo are used to identify the official project by Dmitry Ratner.
You may:
- refer to the project name in a factual way (e.g., "built with WitRPC");
- use the name to indicate compatibility (e.g., "WitRPC-compatible").
You may not:
- use "WitRPC" as the name of a fork or a derived product in a way that implies it is the official project;
- use the WitRPC logo to promote forks or derived products without permission.