{"id":27401300,"url":"https://github.com/edjcase/jsonrpc","last_synced_at":"2025-05-15T09:02:48.554Z","repository":{"id":36145666,"uuid":"40449676","full_name":"edjCase/JsonRpc","owner":"edjCase","description":"Json Rpc Router for Asp.Net Core","archived":false,"fork":false,"pushed_at":"2025-03-18T21:04:20.000Z","size":648,"stargazers_count":142,"open_issues_count":10,"forks_count":42,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-03-18T21:34:33.203Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edjCase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-08-09T20:36:13.000Z","updated_at":"2025-03-18T21:01:59.000Z","dependencies_parsed_at":"2022-07-11T09:33:08.587Z","dependency_job_id":"27d2e807-6737-46d7-9bb2-235a71b38eea","html_url":"https://github.com/edjCase/JsonRpc","commit_stats":{"total_commits":194,"total_committers":20,"mean_commits":9.7,"dds":0.5824742268041236,"last_synced_commit":"261bb5160bbab8afc9b049dfe064ca302d3d172a"},"previous_names":["gekctek/jsonrpc.router"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edjCase%2FJsonRpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edjCase%2FJsonRpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edjCase%2FJsonRpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edjCase%2FJsonRpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edjCase","download_url":"https://codeload.github.com/edjCase/JsonRpc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248819367,"owners_count":21166476,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-14T03:55:00.856Z","updated_at":"2025-04-14T03:55:01.685Z","avatar_url":"https://github.com/edjCase.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# JsonRpc.Router\nA .NetStandard 2.1 IRouter implementation for Json Rpc v2 requests for Microsoft.AspNetCore.Routing.\n\nThe requirements/specifications are all based off of the [Json Rpc 2.0 Specification](http://www.jsonrpc.org/specification)\n\n## Installation\n##### NuGet: [JsonRpc.Router](https://www.nuget.org/packages/EdjCase.JsonRpc.Router/)\n\ndotnet CLI:\n```cs\ndotnet add package EdjCase.JsonRpc.Router\n```\nNuget CLI:\n```cs\nInstall-Package EdjCase.JsonRpc.Router\n```\n\n## Usage\n\n### **Minimum config**\n\nCreate a ASP.NET Core Web Application, reference this library and in the `Startup` class configure the following:\n\nAdd the dependency injected services in the `ConfigureServices` method:\n```cs\npublic void ConfigureServices(IServiceCollection services)\n{\n\tservices.AddJsonRpc();\n}\n```\n\nAdd the JsonRpc router the pipeline in the `Configure` method:\n```cs\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)\n{\n\tapp.UseJsonRpc();\n}\n```\nAdd a RpcController class with public methods:\n```cs\npublic class ItemsController : RpcController\n{\n\tpublic Item Get(int id)\n\t{\n\t\t//Code here...\n\t}\n\t\n\tpublic void Add(Item item)\n\t{\n\t\t//Code here...\n\t}\n}\n```\nThats it! The library will auto detect the controllers that are child classes of `RpcController` and will expose all public methods to the api. The url route in this case will be '/Items' because the controller name is '_Items_'Controller. (If the controller does not end with 'Controller' the route will be the class name)\n\n\n### **Advanced Config**\n\nCreate a ASP.NET Core Web Application, reference this library and in the `Startup` class configure the following:\n\nAdd the dependency injected services in the `ConfigureServices` method:\n```cs\npublic void ConfigureServices(IServiceCollection services)\n{\n\tservices\n\t\t.AddJsonRpc(config =\u003e\n\t\t{\n\t\t\t//(Optional) Hard cap on batch size, will block requests will larger sizes, defaults to no limit\n\t\t\tconfig.BatchRequestLimit = 5;\n\t\t\t//(Optional) If true returns full error messages in response, defaults to false\n\t\t\tconfig.ShowServerExceptions = false;\n\t\t\t//(Optional) Configure how the router serializes requests\n\t\t\tconfig.JsonSerializerSettings = new System.Text.Json.JsonSerializerOptions\n\t\t\t{\n\t\t\t\t//Example json config\n\t\t\t\tIgnoreNullValues = false,\n\t\t\t\tWriteIndented = true\n\t\t\t};\n\t\t\t//(Optional) Configure custom exception handling for exceptions during invocation of the method\n\t\t\tconfig.OnInvokeException = (context) =\u003e\n\t\t\t{\n\t\t\t\tif (context.Exception is InvalidOperationException)\n\t\t\t\t{\n\t\t\t\t\t//Handle a certain type of exception and return a custom response instead\n\t\t\t\t\t//of an internal server error\n\t\t\t\t\tint customErrorCode = 1;\n\t\t\t\t\tvar customData = new\n\t\t\t\t\t{\n\t\t\t\t\t\tField = \"Value\"\n\t\t\t\t\t};\n\t\t\t\t\tvar response = new RpcMethodErrorResult(customErrorCode, \"Custom message\", customData);\n\t\t\t\t\treturn OnExceptionResult.UseObjectResponse(response);\n\t\t\t\t}\n\t\t\t\t//Continue to throw the exception\n\t\t\t\treturn OnExceptionResult.DontHandle();\n\t\t\t};\n\t\t});\n\t\t});\n}\n```\nThere are multiple ways to add JSONRpc middleware in the `Configure` method\n1. Full Auto Detection\n\n```cs\npublic void Configure(IApplicationBuilder app)\n{\n    //This will register all the classes that derive from `RpcController` and their public instance methods\n\tapp.UseJsonRpc();\n}\n```\n2. Derived Controllers Auto Detection\n\n```cs\npublic void Configure(IApplicationBuilder app)\n{\n    //This will register all the classes that derive from `ControllerBase` and their public instance methods\n    //E.g. `ControllerBase` has 3 child classes/controllers (CustomController, OtherController, Commands) so by default \n\t//three routes would be `Custom`, `Other` and `Commands` respectively, but since CustomController is decorated with RpcRouteAttribute(\"Main\"),\n\t//its route will be `Main` instead of `Custom`\n\tapp.UseJsonRpcWithBaseController\u003cControllerBase\u003e();\n}\n```\n3. Manual controller registration\n\n```cs\npublic void Configure(IApplicationBuilder app)\n{\n\tapp.UseJsonRpc(options =\u003e\n    {\n    \toptions\n    \t\t//Will make controller methods available for path '/First', unless overridden by RpcRouteAttribute\n    \t\t//Note that any class will work here, not just a class derived from `RpcController`\n    \t\t.AddController\u003cNonRpcController\u003e()\n    \t\t//Will make controller methods available for custom path '/CustomPath'\n    \t\t//Note that the same controller can be available under multiple routes\n    \t\t.AddControllerWithCustomPath\u003cNonRpcController\u003e(\"CustomPath\");\n    });\n}\n```\n4. Manual method registration\n\n```cs\npublic void Configure(IApplicationBuilder app)\n{\n\tapp.UseJsonRpc(options =\u003e\n    {\n\t\tMethodInfo customControllerMethod1 = typeof(CustomController).GetMethod(\"Method1\");\n\t\tMethodInfo otherControllerMethod1 = typeof(OtherController).GetMethod(\"Method1\");\n\t\toptions\n\t\t\t//Will make the `Method1` method in `CustomController` available with route '/'\n\t\t\t//Note that since that method has `RpcRouteAttribute(\"Method\")`, that will change the method name\n\t\t\t//from `Method1` to `Method` in the router\n\t\t\t.AddMethod(customControllerMethod1)\n\t\t\t//Will make the `Method1` method in `OtherController` available with route '/CustomMethods'\n\t\t\t.AddMethod(otherControllerMethod1, \"CustomMethods\");\n    });\n}\n```\n\n\n## Examples of Rpc Classes:\nRecommended format is to use subclasses of RpcController. These classes will be autodetected if using the UseJsonRpc() method (option 1 from above)\n\n```cs\n[RpcRoute(\"TestMethods\")] //Optional, if not specified the route name would be 'Test' (based off the controller type name)\npublic class TestController : RpcController\n{\n\t//Will return a success response or an error response dependening on the if statement\n\t// (See IRpcMethodResult usage below)\n\tpublic IRpcMethodResult CustomResult()\n\t{\n\t\tif(/*something is invalid*/)\n\t\t{\n\t\t\treturn this.Error(customErrorCode, errorMesssage); //Or return new RpcMethodErrorResult(customErrorCode, errorMessage);\n\t\t}\n\t\treturn this.Ok(optionalReturnObject);//Or return new RpcMethodSuccessResult(optionalReturnObject);\n\t}\n\t\n\t//Returning values is also valid but will never give an error unless an exception is thrown\n\tpublic int Subtract(int a, int b)\n\t{\n\t\treturn a - b;\n\t}    \n\t\n\t//Accessable to api at /{OptionalRoutePrefix}/{OptionalRoute}/Add \n\t//e.g. (from previous example) /RpcApi/Add or /RpcApi/Class2/Add\n\t//Example request using param list: {\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"Add\", \"params\": [1,2]}\n\t//Example request using param map: {\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"Add\", \"params\": {\"a\": 1, \"b\": 2}}\n\t//Example response from a=1, b=2: {\"jsonrpc\", \"2.0\", \"id\": 1, \"result\": 3}\n\tpublic int Add(int a, int b)\n\t{\n\t\treturn a + b;\n\t}\n\t\n\t//This method would use the same request as Add(int a, int b) (except method would be 'AddAsync') \n\t//and would respond with the same response\n\tpublic async Task\u003cint\u003e AddAsync(int a, int b)\n\t{\n\t\t//async adding here\n\t}\n\t\n\t//Can't be called/will return MethodNotFound because it is private. Same with all non-public/static methods.\n\tprivate void Hidden1()\n\t{\n\t}\n}\n```\nAnd or if manually mapping (not auto detection) any class can be used for Rpc calls if configured in `Startup.cs`\n\n```cs\n//Classes can be named anything and be located anywhere in the project/solution\n//The way to associate them to the api is to use the RegisterController\u003cT\u003e method in\n//the configuration\npublic class RpcClass1\n{\n\tpublic int Add(int a, int b)\n\t{\n\t\treturn a + b;\n\t}\n}\n```\n\n\nAny method in the registered class that is a public instance method will be accessable through the Json Rpc Api.\n\nThe controllers and manual registration CAN be used at the same time. Mix and match as needed.\n\n## Custom Rpc Responses\nIn order to specify different types of responses (such as errors and successful result objects) in the same method `IRpcMethodResult` can be used as a return type. If the router detects the returned object is a `IRpcMethodResult` then it will call the `ToRpcReponse(...)` method and use that as the response. The default implementations are for simple error and success routes. The `RpcMethodErrorResult` will use the error code, message and data to create an error response. The `RpcMethodSuccessResult` will use the optional return object to create a successful response.\n\nAny custom implementation of the `IRpcMethodResult` can be used for application specific purposes. One common use may be to unify the custom rpc error codes that one specific application uses.\n\nThere are two helper methods in the RpcController class: `this.Ok(obj)` and `this.Error(code, message, data)`. They are just wrappers around the implementations of `IRpcMethodResult`. So `return this.Ok(obj);` is equivalent to `return new RpcMethodSuccessResult(obj)`.\n\n## Misc\n\nBulk requests are supported (as specificed in JsonRpc 2.0 docs) and will all be run asynchronously. The responses may be in a different order than the requests.\n\nOn specifics on how to create requests and what to expect from responses, use the [Json Rpc 2.0 Specification](http://www.jsonrpc.org/specification).\n\n## Contributions\n\nContributions welcome. Fork as much as you want. All pull requests will be considered.\n\nBest way to develop is to use Visual Studio 2015+ or Visual Studio Code on other platforms besides windows.\n\nAlso the correct dnx runtime has to be installed if visual studio does not automatically do that for you. \nInformation on that can be found at the [Asp.Net Repo](https://github.com/aspnet/Home).\n\nNote: I am picky about styling/readability of the code. Try to keep it similar to the current format. \n\n## Feedback\nIf you do not want to contribute directly, feel free to do bug/feature requests through github or send me and email [Gekctek@Gmail.com](mailto:Gekctek@Gmail.com)\n\n### Todos\n\n - Better sample app\n - Performance testing\n\nLicense\n----\n[MIT](https://raw.githubusercontent.com/Gekctek/JsonRpc.Router/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedjcase%2Fjsonrpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedjcase%2Fjsonrpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedjcase%2Fjsonrpc/lists"}