Skip to content

Cooke/cooke-rpc

Repository files navigation

Cooke RPC

A set of libraries and tools for easy RPC (Remote Procedure Call) implementation on .NET (Core) and consumption from JS and TypeScript.

Key features

  • Code first
  • Generated schema
  • Pluggable architecture (enabling custom serialization, transport channels and protocols)
  • Polymorphic (de)serialization via JSON (System.Text.Json) or MessagePack

Alternative techniques and comparisons

Some relevant alternative technologies with potentially main drawbacks compared to Cooke RPC:

  • GraphQL with Hot Chocolate and Apollo Client
    • Querying requires explicit declaration of all fields to fetch
    • No support for input union types
  • ASP.NET Core (Web API) + Open API/Swagger
    • Http only (no direct consumption for instance via web sockets)
    • Generic / less opiniated
  • GRPC with GRPC-DOTNET
    • Requires HTTP2
    • Protobuf

Backend usage with ASP.NET Core

Install nuget package:

dotnet add package CookeRpc.AspNetCore

Add required services:

protected override void ConfigureServices(IServiceCollection services)
{
    services.AddRpc();
}

Plugin middleware (defaults to path "/rpc"):

protected override void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseRpc();
}

Implement service:

[RpcService]
[Authorize] // If an authenticated user is required
public class MyService
{
    public async Task<int> GetPi() {
        return Math.PI;
    }

    public async Task<int> Add(int left, int right) {
        return left + right;
    }

    // Context parameter is set by library and is not exposed externally 
    [Authorize("OperationAccessPolicy")]
    public async Task<OutputType?> Operation(RpcContext context, InputType input) {
        return null;
    }
}

Front-end usage with TypeScript

Install npm packages:

npm add cooke-rpc
npm add -D cooke-rpc-tooling

Generate types and procedures:

cooke-rpc generate https://localhost:5001/rpc ./src/generated/rpc.ts

Usage:

import { sendJsonRpc } from "cooke-rpc";
import { myService } from "./generated/rpc";

const result = await sendJsonRpc(myService.add(1, 2), async (json: string) => {
  // Library consumer needs to implement actual transmission
  const response = await fetch("https://localhost:5001/rpc", {
    method: "POST",
    mode: "cors",
    credentials: "include",
    body: json,
  });

  return await response.text();
});

Usage from React

Install react hooks:

npm add cooke-rpc-react

Create RPC dispatcher and add to context:

import React from "react";
import { render } from "react-dom";

import { RpcClientProvider, createClient } from "cooke-rpc-react";

function App() {
  const [rpcDispatcher] = useState<RpcDispatcher>(
    () => (invocation: RpcInvocation<any>) =>
      sendJsonRpc(invocation, async (json: string) => {
        // Library consumer needs to implement actual transmission
        const response = await fetch(config.serverUrl + "/rpc", {
          method: "POST",
          mode: "cors",
          credentials: "include",
          body: json,
        });

        return await response.text();
      })
  );
  return (
    <RpcDispatcherProvider dispatcher={rpcDispatcher}>
      <div>Your app goes here</div>
    </RpcDispatcherProvider>
  );
}

render(<App />, document.getElementById("root"));

Use RPC:

import { useRpc, useRpcFetch } from "cooke-rpc-react";
import { myService } from "./generated/rpc";

export const AddComponent = (props: { left: number; right: number }) => {
  const { error, invoke, invoking, result, setResult } = useRpc(
    myService.add,
    props.left,
    props.right
  );
  return (
    <button onClick={invoke}>Calculate result: {result ?? "no result"}</button>
  );
};

export const PiComp = () => {
  // Instantly invokes the RPC, useful for querying on component mount
  const { error, refetch, fetching, result } = useRpcFetch(myService.getPi);
  return <div>{result ?? "Fetching PI"}</div>;
};

About

Simple RPC from JS clients to .NET services

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published