RPC library (.NET Standard 2.0) with classic .NET Remoting flavour
NuGet package: https://www.nuget.org/packages/CoreRemoting/
Documentation: https://github.com/theRainbird/CoreRemoting/wiki
- To help migrate applications that use .NET Remoting to .NET Core / .NET 5 / .NET 6.
- To provide easy-to-use RPC functionality
- To support events and delegates in a distributed application
- To run on Linux, Windows and Mac
- To create REST-APIs for Javascript clients
- To create SOAP Webservices
- To use with other platforms than .NET
- To create server applications that needs to run on several cluster nodes
- Support for cross framework serialization (since version 1.2.0.0)
- Creates proxy objects for remote services at runtime (uses Castle.DynamicProxy under the hood)
- Services can have
SingleCallorSingetonlifetime - Uses duplex TCP network communication by default (based on WatsonTcp library)
- Supports Named Pipe channel for inter-process communication (since version 1.3.0.0)
- Custom transport channels can be plugged in (Just implement
IServerChannelandIClientChannel) - Used Bson serialization by default (via Json.NET)
- Includes NeoBinaryFormatter as built-in binary serializer
- BinaryFormatter support is available in separate CoreRemoting.Serialization.Binary package
- BinaryFormatter is hardened against known deserialization attack patterns
- Custom serializers can be plugged in (Just implement
ISerializerAdapter) - Support for custom authentication (Just implement
IAuthenticationProvider) - Pluggable authentication provider to authenticate Linux user on server with PAM is available
- Pluggable authentication provider to authenticate Windows user on server is available
- Message encryption with RSA key exchange and AES (No SSL, no X509 certificates needed, works also on Linux)
- Supports .NET Remoting style
CallContext(also on .NET Core / .NET 5) to implicitly transfer objects on RPC calls / threads - Supports Microsoft Dependency Injection (Just call
AddCoreRemotingServerorAddCoreRemotingClienton yourIServiceCollection) - Supports also Castle Windsor Container to provide Dependecy Injection
- Built-in session management
- Automatic sweeping of inactive sessions
- Keep session alive feature
- Can be used in Blazor Server projects to communicate to a central application server
- Supports Linq Expression parameters
- Supports remote invocation of async methods (async / await)
Let's create a simple multi user chat server as hello world application.
To be able to call a remote service, the client needs to know an interface implemented by the service. This interfaces should be placed in a shared assembly (Just like it is common with .NET remoting)
namespace HelloWorld.Shared
{
public interface ISayHelloService
{
event Action<string, string> MessageReceived;
void Say(string name, string message);
}
}The server side application provides services to clients.
using System;
using CoreRemoting;
using CoreRemoting.DependencyInjection;
using HelloWorld.Shared;
namespace HelloWorld.Server
{
public class SayHelloService : ISayHelloService
{
// Event to notify clients when users post new chat messages
public event Action<string, string> MessageReceived;
// Call via RPC to say something in the chat
public void Say(string name, string message)
{
MessageReceived?.Invoke(name, message);
}
}
public static class HelloWorldServer
{
static void Main(string[] args)
{
using var server = new RemotingServer(new ServerConfig()
{
HostName = "localhost",
NetworkPort = 9090,
RegisterServicesAction = container =>
{
// Make SayHelloSevice class available for RPC calls from clients
container.RegisterService<ISayHelloService, SayHelloService>(ServiceLifetime.Singleton);
}
});
server.Start();
Console.WriteLine("Server is running.");
Console.ReadLine();
}
}
}The client consumes remote services hosted on the server.
using System;
using CoreRemoting;
using HelloWorld.Shared;
namespace HelloWorld.Client
{
public static class HelloWorldClient
{
static void Main(string[] args)
{
using var client = new RemotingClient(new ClientConfig()
{
ServerHostName = "localhost",
ServerPort = 9090
});
client.Connect();
// Create a proxy of the remote service, which behaves almost like a regular local object
var proxy = client.CreateProxy<ISayHelloService>();
// Receive chat messages send by other remote users by event
proxy.MessageReceived += (senderName, message) =>
Console.WriteLine($"\n {senderName} says: {message}\n");
Console.WriteLine("What's your name?");
var name = Console.ReadLine();
Console.WriteLine("\nEntered chat. Type 'quit' to leave.");
bool quit = false;
while (!quit)
{
var text = Console.ReadLine();
if (text != null && text.Equals("quit", StringComparison.InvariantCultureIgnoreCase))
quit = true;
else
{
// Post a new chat message
proxy.Say(name, text);
}
}
}
}
}Source code of this example is also available in the repository at https://github.com/theRainbird/CoreRemoting/tree/master/Examples/HelloWorld.
To test the hello world solution, start the server (HelloWorld.Server) and then multiple clients (HelloWorld.Client). Have fun.
A new binary serializer is now included in the core system:
- Name: NeoBinaryFormatter
- Location: Built into CoreRemoting core assembly
- Benefits: Better security than classic BinaryFormatter, also supports DataSets/DataTables if needed
- Performance: Currently slower than BinaryFormatter but faster than Hyperion (performance improvements in progress)
- Usage: Recommended binary serializer when binary serialization is desired (BSON from Newtonsoft remains default)
Starting with version 1.3, the classic BinaryFormatter support has been moved to a separate assembly:
- Package:
CoreRemoting.Serialization.Binary - Purpose: Maintains compatibility for applications requiring DataSet/DataTable serialization
- Security: Includes hardened BinaryFormatter implementation against deserialization attacks
Version 1.3 introduces a new Named Pipe channel for inter-process communication:
- Purpose: High-performance communication between processes on the same machine
- Benefits: Works without network stack (no TCP port needed) for local inter-process communication
- Usage: Ideal for client-server applications running on the same host
If you were using BinaryFormatter in version 1.2 or earlier:
- For new applications requiring binary serialization, use NeoBinaryFormatter (recommended)
- For existing Applications that are using BinaryFormatter and requiring 100% compatibility, add the
CoreRemoting.Serialization.BinaryNuGet package - Update your serializer configuration to use the appropriate serializer adapter