/aspnetcore-json-rpc

JSON-RPC 2.0 middleware for ASP.NET Core 2

Primary LanguageC#MIT LicenseMIT

Anemonis.AspNetCore.JsonRpc

JSON-RPC 2.0 middleware for ASP.NET Core 2 based on the JSON-RPC 2.0 Transport: HTTP specification and the Anemonis.JsonRpc serializer.

NuGet package Gitter

Project Details

  • The middleware transparently handles batch JSON-RPC requests.
  • The middleware automatically handles common JSON-RPC issues.
  • The middleware does not verify the Content-Length header.
  • A service supports default method parameter values for named parameters not provided in a request.

In addition to the standard JSON-RPC error codes the middleware may return the following JSON-RPC errors:

Code Reason
-32000 The provided batch contains requests with duplicate identifiers

In addition to the standard JSON-RPC HTTP error codes the middleware may return the following HTTP error codes:

Code Reason
415 The Content-Encoding header is specified

According to the current logging configuration, the following events may appear in a journal:

ID Level Reason
1000 Debug A JSON-RPC request accepted for processing as a single item
1010 Debug A JSON-RPC request accepted for processing as a batch
2000 Information A JSON-RPC request processed as notification
2010 Information A JSON-RPC request processed with result
2020 Information A JSON-RPC request processed with error
2030 Information A JSON-RPC request processed with result as notification due to client demand
2040 Information A JSON-RPC request processed with error as notification due to client demand
3000 Warning A JSON-RPC request processed as notification due to server configuration
4000 Error An error occurred during deserialization of a JSON-RPC request
4010 Error A JSON-RPC request is not considered as a valid JSON-RPC message
4020 Error A JSON-RPC batch contains requests with duplicate identifiers

Code Examples

[JsonRpcRoute("/api")]
public class JsonRpcService : IJsonRpcService
{
    [JsonRpcMethod("m1", "p1", "p2")]
    public Task<long> InvokeMethod1Async(long p1, long p2)
    {
        if (p2 == 0L)
        {
            throw new JsonRpcServiceException(100L);
        }

        return Task.FromResult(p1 / p2);
    }

    [JsonRpcMethod("m2", 0, 1)]
    public Task<long> InvokeMethod2Async(long p1, long p2)
    {
        return Task.FromResult(p1 + p2);
    }
}

public class Startup : IStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddJsonRpc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseJsonRpc();
    }
}

or

[JsonRpcRoute("/api")]
public class JsonRpcHandler : IJsonRpcHandler
{
    public IReadOnlyDictionary<string, JsonRpcRequestContract> GetContracts()
    {
        var contract1Types = new Dictionary<string, Type>();
        var contract2Types = new Type[2];

        contract1Types["p1"] = typeof(long);
        contract1Types["p2"] = typeof(long);
        contract2Types[0] = typeof(long);
        contract2Types[1] = typeof(long);

        var contracts = new Dictionary<string, JsonRpcRequestContract>();

        contracts["m1"] = new JsonRpcRequestContract(contract1Types);
        contracts["m2"] = new JsonRpcRequestContract(contract2Types);

        return contracts;
    }

    public Task<JsonRpcResponse> HandleAsync(JsonRpcRequest request)
    {
        var response = default(JsonRpcResponse);

        switch (request.Method)
        {
            case "m1":
                {
                    var p1 = (long)request.ParametersByName["p1"];
                    var p2 = (long)request.ParametersByName["p2"];

                    response = p2 != 0L ?
                        new JsonRpcResponse(p1 / p2, request.Id) :
                        new JsonRpcResponse(new JsonRpcError(100L), request.Id);
                }
                break;
            case "m2":
                {
                    var p1 = (long)request.ParametersByPosition[0];
                    var p2 = (long)request.ParametersByPosition[1];

                    response = new JsonRpcResponse(p1 + p2, request.Id);
                }
                break;
        }

        return Task.FromResult(response);
    }
}

public class Startup : IStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddJsonRpc();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseJsonRpc();
    }
}

Quicklinks