All notable changes to the WitRPC project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[2.3.0] - 2025-12-09
Added
BouncyCastle Cross-Platform Encryption
- New Package:
OutWit.Communication.Client.Encryption.BouncyCastle- Cross-platform encryption client using BouncyCastle cryptography library - New Package:
OutWit.Communication.Server.Encryption.BouncyCastle- Cross-platform encryption server using BouncyCastle cryptography library - Pure C# implementation that works everywhere, including Blazor WebAssembly without JavaScript interop
- RSA-OAEP (SHA-256) for key exchange, AES-256-CBC for symmetric encryption
- Extension methods
WithBouncyCastleEncryption()for easy configuration
// Client (works in Blazor WebAssembly!)
var client = WitClientBuilder.Build(options =>
{
options.WithWebSocket("ws://localhost:5000");
options.WithJson();
options.WithBouncyCastleEncryption(); // Cross-platform encryption
});
// Server
var server = WitServerBuilder.Build(options =>
{
options.WithWebSocket("http://localhost:5000", maxClients: 100);
options.WithJson();
options.WithBouncyCastleEncryption(); // Must match client
options.WithService(myService);
});Important: BouncyCastle encryption is NOT compatible with standard .NET encryption. Both client and server must use
WithBouncyCastleEncryption().
Composite Services (Multiple Interfaces per Server)
- New Class:
CompositeRequestProcessor- Request processor that handles multiple service interfaces - New Builder:
CompositeServiceBuilder- Fluent builder for registering multiple services - Allows clients to request proxies for different interfaces from a single server connection
- Eliminates the need to create "super-interfaces" that inherit from multiple service interfaces
// Server: Register multiple services
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: Access any registered service
var userService = client.GetService<IUserService>();
var orderService = client.GetService<IOrderService>();
var notificationService = client.GetService<INotificationService>();Composite Services with Dependency Injection
- New Method:
AddWitRpcServerWithServices()- Register composite services with automatic DI resolution - New Class:
CompositeServiceRegistration- Helper for configuring composite services in DI context - Services can be resolved from DI container or registered inline
- Three registration patterns: pre-registered services, inline registration, and factory functions
// Option 1: Services already registered in DI
services.AddSingleton<IUserService, UserServiceImpl>();
services.AddSingleton<IOrderService, OrderServiceImpl>();
services.AddWitRpcServerWithServices("api-server",
options =>
{
options.WithTcp(5000, maxClients: 100);
options.WithJson();
},
svcs =>
{
svcs.AddService<IUserService>(); // Resolved from DI
svcs.AddService<IOrderService>(); // Resolved from DI
});
// Option 2: Register and add in one step
services.AddWitRpcServerWithServices("api-server",
options => { /* ... */ },
svcs =>
{
svcs.AddService<IUserService, UserServiceImpl>();
svcs.AddService<IOrderService, OrderServiceImpl>();
});
// Option 3: Factory functions
services.AddWitRpcServerWithServices("api-server",
options => { /* ... */ },
svcs =>
{
svcs.AddService<IUserService>(sp => new UserServiceImpl(
sp.GetRequiredService<ILogger<UserServiceImpl>>()));
});Dependency Injection Integration
- New Package:
OutWit.Communication.Client.DependencyInjection- Microsoft.Extensions.DependencyInjection support for WitRPC clients - New Package:
OutWit.Communication.Server.DependencyInjection- Microsoft.Extensions.DependencyInjection support for WitRPC servers - Seamless integration with ASP.NET Core and other DI-based applications
- Extension methods for
IServiceCollection
// Register WitRPC client with DI
services.AddWitRpcClient("my-client", (options, sp) =>
{
options.WithWebSocket("ws://localhost:5000");
options.WithJson();
options.WithEncryption();
});
// Inject and use
public class MyController
{
private readonly IWitClient _client;
public MyController(IWitClientFactory factory)
{
_client = factory.GetClient("my-client");
}
}Auto-Reconnection
- New Class:
ReconnectionOptions- Configurable reconnection settings - Automatic reconnection with exponential backoff
- Configurable max attempts, initial delay, max delay, and jitter
- Extension method
WithAutoReconnect()for easy configuration
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);
reconnect.UseJitter = true;
});
});Retry Policy / Resilience
- New Class:
RetryPolicy- Configurable retry settings for failed RPC calls - Support for fixed and exponential backoff strategies
- Configurable retry conditions (which exceptions to retry)
- Extension method
WithRetryPolicy()for easy configuration
var client = WitClientBuilder.Build(options =>
{
options.WithTcp("localhost", 5000);
options.WithJson();
options.WithRetryPolicy(retry =>
{
retry.MaxRetries = 3;
retry.InitialDelay = TimeSpan.FromMilliseconds(100);
retry.BackoffMultiplier = 2.0;
retry.MaxDelay = TimeSpan.FromSeconds(5);
});
});Health Checks
- New Package:
OutWit.Communication.Client.HealthChecks- ASP.NET Core Health Checks support - Monitor WitRPC client connection status
- Integration with standard ASP.NET Core health check infrastructure
// Register health check
services.AddHealthChecks()
.AddWitRpcClientCheck("my-client", tags: new[] { "rpc", "ready" });
// Use in ASP.NET Core
app.MapHealthChecks("/health");Server Encryption Interface Enhancement
- Added
EncryptForClient(byte[] data, byte[] clientPublicKey)method toIEncryptorServerinterface - Enables server-side encryption implementations to encrypt data using client's public key
- Required for BouncyCastle encryption support
CI/CD
- New Workflow:
publish-package.yml- GitHub Action for publishing individual NuGet packages - New Workflow:
publish-all-packages.yml- GitHub Action for publishing all packages in parallel - Supports publishing to both nuget.org and GitHub Packages
- Includes all Communication and InterProcess packages
Test Infrastructure
- Added
[assembly: Parallelizable(ParallelScope.None)]to disable parallel test execution - Prevents port/resource conflicts when running tests in bulk
- New test interfaces and implementations for composite service testing
- Integration tests for BouncyCastle encryption and composite services
Changed
Documentation
- Updated
README.mdforOutWit.Communication.Serverwith composite services documentation - Updated
README.mdforOutWit.Communication.Clientwith multiple service access documentation - Updated
README.mdforOutWit.Communication.Server.DependencyInjectionwith composite services DI documentation - Created comprehensive README files for BouncyCastle encryption packages with compatibility tables
- Updated main
README.mdwith full package list, badges, and advanced features documentation - Created
CHANGELOG.mdfor tracking version history
Fixed
- Improved test stability when running multiple tests sequentially
[2.2.0] - 2025-11-14
See repository history for previous changes.
Full history and diffs: CHANGELOG.md on GitHub.