Lakerfield.Rpc

April 17, 2025 ยท View on GitHub

Lakerfield.Rpc is a flexible RPC implementation for .NET, enabling remote procedure calls over WebSockets (with optional TCP support) using BSON for message serialization via the MongoDB.Bson / Lakerfield.Bson library.

Features

  • Define a single interface to represent your RPC contract; source generators automatically generate all client and server code based on that interface
  • Supports WebSocket transport (TCP support available)
  • Compact, binary messages with BSON serialization

Requirements

  • .NET 8.0 or higher

Installation

Install the core RPC library:

dotnet add package Lakerfield.Rpc
dotnet add package Lakerfield.Rpc.SourceGenerator

Install the client RPC libary:

dotnet add package Lakerfield.Rpc.SourceGenerator
dotnet add package Lakerfield.Rpc.WebSocketClient

Install the server RPC libary:

dotnet add package Lakerfield.Rpc.SourceGenerator
dotnet add package Lakerfield.Rpc.WebSocketServer

Dependencies

  • Lakerfield.Bson: A fork of MongoDB.Bson (with only a namespace change) to avoid conflicts when using MongoDB.Bson in your application, used for efficient BSON serialization.
  • System.Reactive: Required by both WebSocket client and server for reactive message handling.
  • Microsoft.AspNetCore.App: Framework reference for the WebSocket server.

Usage Example (WebSocket)

Shared libary with the interface and bson configuration

[RpcService]
public interface IRpcTestService
{
  Task<Company> CompanyFindById(Guid id);
}

public static partial class RpcTestServiceBsonConfigurator
{
  static partial void PreConfigure()
  {
    // configure bson mapping of the models
    Lakerfield.Bson.Serialization.BsonClassMap.RegisterClassMap<Models.Company>(AutoMap);
  }
}

WebSocket Client

var networkClient = new NetworkClient(new Uri("ws://localhost/ws"));
var client = new RpcTestServiceClient(networkClient);

var company = await client.CompanyFindById(Guid.NewGuid());
[RpcClient]
public partial class RpcTestServiceClient : IRpcTestService
{
  // implementation is generated by sourcegenerator
}

WebSocket Server

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRpcWebSocketServer<IRpcTestService, RpcTestWebSocketServiceServer>();

var app = builder.Build();

app.UseWebSockets(new WebSocketOptions
{
  KeepAliveInterval = TimeSpan.FromSeconds(120),
  AllowedOrigins = { "*" } // Pas dit aan voor productie!
});
app.UseRpcWebSocketServer<IRpcTestService>("/ws");

await app.RunAsync();
[RpcServer]
public partial class RpcTestWebSocketServiceServer : Lakerfield.Rpc.LakerfieldRpcWebSocketServer<IRpcTestService>
{
  public override ILakerfieldRpcClientMessageHandler CreateConnectionMessageRouter(LakerfieldRpcWebSocketServerConnection connection)
  {
    return new ClientConnectionMessageHandler(connection as LakerfieldRpcWebSocketServerConnection<IRpcTestService>);
  }

  public partial class ClientConnectionMessageHandler // implements IRpcTestService
  {
    public async Task<Models.Company> CompanyFindById(System.Guid id)
    {
      return new Models.Company()
      {
        Id = id.ToString(),
        Name = "The company",
      };
    }
}

Example Project

See the complete WebSocket demo in the RpcDemo projects of the rosacode repository:

https://github.com/Lakerfield/rosacode

Contributing

Contributions, issues, and feature requests are welcome. Please see CONTRIBUTING.md for guidelines.

License

This project is licensed under the MIT License. See LICENSE for details.