diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..bdb0cab
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,17 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Custom for Visual Studio
+*.cs diff=csharp
+
+# Standard to msysgit
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
diff --git a/.github/workflows/build_publish_master.yml b/.github/workflows/build_publish_master.yml
new file mode 100644
index 0000000..1a7fe10
--- /dev/null
+++ b/.github/workflows/build_publish_master.yml
@@ -0,0 +1,33 @@
+name: Build Master
+on:
+ push:
+ paths-ignore:
+ - "**/*.md"
+ branches: [ master ]
+
+jobs:
+ build:
+
+ strategy:
+ matrix:
+ os: ['ubuntu-latest']
+ dotnet-version: ['3.1.201']
+ project : ['Json-Rpc']
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: ${{matrix.dotnet-version}}
+ - name: Install dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build ${{matrix.project}} --configuration Release
+ - name: Test
+ run: dotnet test AustinHarris.JsonRpcTestN
+ # Publish
+ - name: publish nuget version change
+ run: dotnet nuget push Json-Rpc/bin/Release/*.nupkg --skip-duplicate --source "https://www.nuget.org" --api-key ${{secrets.NugetKey}} # API key for the NuGet feed
diff --git a/.github/workflows/build_pull_request.yml b/.github/workflows/build_pull_request.yml
new file mode 100644
index 0000000..f3e06e9
--- /dev/null
+++ b/.github/workflows/build_pull_request.yml
@@ -0,0 +1,35 @@
+name: Pull Reqest
+on:
+ pull_request:
+ paths-ignore:
+ - "**/*.md"
+ branches: [ master ]
+
+jobs:
+ build:
+
+ strategy:
+ matrix:
+ os: ['windows-latest','ubuntu-latest']
+ dotnet-version: ['3.1.201']
+ project : ['Json-Rpc']
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: ${{matrix.dotnet-version}}
+ - name: Install dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build ${{matrix.project}} --configuration Release --version-suffix ci-${{ github.run_id }}-${{ github.run_number }}
+ - name: Test
+ run: dotnet test AustinHarris.JsonRpcTestN
+ # Publish
+ - name: publish nuget version change
+ if: ${{matrix.os == 'ubuntu-latest'}}
+ run: dotnet nuget push Json-Rpc/bin/Release/*.nupkg --skip-duplicate --source "https://www.nuget.org" --api-key ${{secrets.NugetKey}} # API key for the NuGet feed
+
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index bdc3535..6ea46be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -106,3 +106,5 @@ Generated_Code #added for RIA/Silverlight projects
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
+.nuget/NuGet.exe
+.vs/
diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config
new file mode 100644
index 0000000..67f8ea0
--- /dev/null
+++ b/.nuget/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.nuget/NuGet.targets b/.nuget/NuGet.targets
new file mode 100644
index 0000000..a6dbdfb
--- /dev/null
+++ b/.nuget/NuGet.targets
@@ -0,0 +1,90 @@
+
+
+
+ $(MSBuildProjectDirectory)\..\
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
+
+
+
+
+ $(SolutionDir).nuget
+
+
+
+ $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config
+ $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config
+
+
+
+ $(MSBuildProjectDirectory)\packages.config
+ $(PackagesProjectConfig)
+
+
+
+
+ $(NuGetToolsPath)\NuGet.exe
+ @(PackageSource)
+
+ "$(NuGetExePath)"
+ mono --runtime=v4.0.30319 "$(NuGetExePath)"
+
+ $(TargetDir.Trim('\\'))
+
+ -RequireConsent
+ -NonInteractive
+
+ "$(SolutionDir) "
+ "$(SolutionDir)"
+
+
+ $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
+ $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
+
+
+
+
+
+
+ $(BuildDependsOn);
+ BuildPackage;
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AustinHarris.JsonRpc.AspNet/AustinHarris.JsonRpc.AspNet.csproj b/AustinHarris.JsonRpc.AspNet/AustinHarris.JsonRpc.AspNet.csproj
index e31b302..3470e2c 100644
--- a/AustinHarris.JsonRpc.AspNet/AustinHarris.JsonRpc.AspNet.csproj
+++ b/AustinHarris.JsonRpc.AspNet/AustinHarris.JsonRpc.AspNet.csproj
@@ -15,6 +15,8 @@
SAK
SAK
SAK
+ ..\
+ true
true
@@ -34,9 +36,9 @@
4
-
- False
- ..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll
+
+ ..\packages\Newtonsoft.Json.12.0.3\lib\net40\Newtonsoft.Json.dll
+ True
@@ -45,6 +47,7 @@
+
@@ -57,6 +60,13 @@
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
-
\ No newline at end of file
diff --git a/AustinHarris.JsonRpcTest/Properties/AssemblyInfo.cs b/AustinHarris.JsonRpcTest/Properties/AssemblyInfo.cs
deleted file mode 100644
index 8fe95b7..0000000
--- a/AustinHarris.JsonRpcTest/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("AustinHarris.JsonRpcTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("AustinHarris.JsonRpcTest")]
-[assembly: AssemblyCopyright("Copyright © 2014")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("45d95cf9-ddf4-4eda-add0-80f5222a2a38")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AustinHarris.JsonRpcTestN/AustinHarris.JsonRpcTestN.csproj b/AustinHarris.JsonRpcTestN/AustinHarris.JsonRpcTestN.csproj
new file mode 100644
index 0000000..c5db038
--- /dev/null
+++ b/AustinHarris.JsonRpcTestN/AustinHarris.JsonRpcTestN.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Austin Harris
+ netcoreapp3.0;netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AustinHarris.JsonRpcTest/UnitTest1.cs b/AustinHarris.JsonRpcTestN/Test.cs
similarity index 59%
rename from AustinHarris.JsonRpcTest/UnitTest1.cs
rename to AustinHarris.JsonRpcTestN/Test.cs
index feecd71..ed46543 100644
--- a/AustinHarris.JsonRpcTest/UnitTest1.cs
+++ b/AustinHarris.JsonRpcTestN/Test.cs
@@ -1,191 +1,237 @@
-using System;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using AustinHarris.JsonRpc.Client;
+using NUnit.Framework;
+using System;
+using System.Linq;
using AustinHarris.JsonRpc;
+using System.Text.RegularExpressions;
+using Newtonsoft.Json.Linq;
-namespace UnitTests
+namespace AustinHarris.JsonRpcTestN
{
- [TestClass]
- public class UnitTest1
+ public class Poco
{
- static object[] services ;
+ public static Poco WithOffset(int offset)
+ {
+ return new Poco(offset);
+ }
+
+ readonly int _offset;
+ public Poco(int offset)
+ {
+ _offset = offset;
+ }
+
+ [JsonRpcMethod("add")]
+ public int Add(int input) { return input + _offset; }
+ }
+
+ [TestFixture()]
+ public class Test
+ {
+ [Test()]
+ public void TestCase()
+ {
+ }
+ static object[] services;
- static UnitTest1()
+ static Test()
{
services = new object[] {
- new CalculatorService()};
-
+ new CalculatorService()};
}
- [TestMethod]
+ [Test()]
+ public void TestCanCreateMultipleServicesOfSameTypeInTheirOwnSessions()
+ {
+ Func request = (int param) => String.Format("{{method:'add',params:[{0}],id:1}}", param);
+ Func expectedResult = (int param) => String.Format("{{\"jsonrpc\":\"2.0\",\"result\":{0},\"id\":1}}", param);
+
+ for (int i = 0; i < 100; i++)
+ {
+ ServiceBinder.BindService(i.ToString(), Poco.WithOffset(i));
+ }
+
+ for (int i = 0; i < 100; i++)
+ {
+ var result = JsonRpcProcessor.Process(i.ToString(), request(10));
+ result.Wait();
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult(10 + i));
+ Assert.AreEqual(expected1, actual1);
+ }
+ }
+
+ [Test()]
+ public void TestCanCreateAndRemoveSession()
+ {
+ var h = JsonRpc.Handler.GetSessionHandler("this one");
+ var metadata = new System.Collections.Generic.List> {
+ Tuple.Create ("sooper", typeof(string)),
+ Tuple.Create ("returns", typeof(string))
+ }.ToDictionary(x => x.Item1, x => x.Item2);
+ h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(),new Func(x => "workie ... " + x));
+
+ string request = @"{method:'workie',params:{'sooper':'good'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}";
+ string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}";
+ var result = JsonRpcProcessor.Process("this one", request);
+ result.Wait();
+
+
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult);
+ Assert.IsTrue(JToken.DeepEquals(expected1, actual1));
+
+ h.Destroy();
+
+ var result2 = JsonRpcProcessor.Process("this one", request);
+ result2.Wait();
+
+ Assert.IsTrue(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result)));
+ }
+
+ [Test()]
public void TestInProcessClient()
{
string request = @"{method:'NullableFloatToNullableFloat',params:[0.0],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.AreEqual(result.Result, expectedResult);
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void NullableDateTimeToNullableDateTime()
{
string request = @"{method:'NullableDateTimeToNullableDateTime',params:['2014-06-30T14:50:38.5208399+09:00'],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"2014-06-30T14:50:38.5208399+09:00\",\"id\":1}";
+ var expectedDate = DateTime.Parse("2014-06-30T14:50:38.5208399+09:00");
var result = JsonRpcProcessor.Process(request);
result.Wait();
- Assert.AreEqual(result.Result, expectedResult);
- Assert.AreEqual(expectedResult, result.Result);
+ var acutalDate = DateTime.Parse(result.Result.Substring(27, 33));
+ Assert.AreEqual(expectedDate, acutalDate);
}
- [TestMethod]
- public void NullableFloatToNullableFloat()
+ [TestCase(@"{method:'NullableFloatToNullableFloat',params:[1.2345],id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.2345,\"id\":1}")]
+ [TestCase(@"{method:'NullableFloatToNullableFloat',params:[3.14159],id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":3.14159,\"id\":1}")]
+ [TestCase(@"{method:'NullableFloatToNullableFloat',params:[null],id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}")]
+ public string NullableFloatToNullableFloat(string request)
{
- string request = @"{method:'NullableFloatToNullableFloat',params:[1.2345],id:1}";
- string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.2345,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
- result.Wait();
- Assert.AreEqual(result.Result, expectedResult);
- Assert.AreEqual(expectedResult, result.Result);
- }
-
- [TestMethod]
- public void NullableFloatToNullableFloat3()
- {
- string request = @"{method:'NullableFloatToNullableFloat',params:[3.14159],id:1}";
- string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":3.14159,\"id\":1}";
var result = JsonRpcProcessor.Process(request);
result.Wait();
- Assert.AreEqual(result.Result, expectedResult);
- Assert.AreEqual(expectedResult, result.Result);
+ return result.Result;
}
-
-
- [TestMethod]
- public void NullableFloatToNullableFloat2()
- {
- string request = @"{method:'NullableFloatToNullableFloat',params:[null],id:1}";
- string expectedResult = "{\"jsonrpc\":\"2.0\",\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
- result.Wait();
- Assert.AreEqual(result.Result, expectedResult);
- Assert.AreEqual(expectedResult, result.Result);
- }
-
- [TestMethod]
+
+
+ [Test()]
public void DecimalToNullableDecimal()
{
string request = @"{method:'DecimalToNullableDecimal',params:[0.0],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.0,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.AreEqual(result.Result, expectedResult);
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void StringToListOfString()
{
string request = @"{method:'StringToListOfString',params:['some string'],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.AreEqual(result.Result, expectedResult);
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void CustomStringToListOfString()
{
string request = @"{method:'CustomStringToListOfString',params:[{str:'some string'}],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"one\",\"two\",\"three\",\"some string\"],\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.AreEqual(result.Result, expectedResult);
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void StringToThrowingException()
{
string request = @"{method:'StringToThrowingException',params:['some string'],id:1}";
- string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32603,\"message\":\"Internal Error\",\"data\":";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
- Assert.IsTrue(result.Result.StartsWith(expectedResult));
+ StringAssert.Contains("-32603", result.Result);
}
- [TestMethod]
+ [Test()]
public void StringToRefException()
{
string request = @"{method:'StringToRefException',params:['some string'],id:1}";
- string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-1,\"message\":\"refException worked\",\"data\":null},\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"refException worked\",\"code\":-1,\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
- Assert.IsTrue(result.Result.StartsWith(expectedResult));
- Assert.AreEqual(expectedResult, result.Result);
+ Assert.IsTrue(JToken.DeepEquals(JObject.Parse(expectedResult), JObject.Parse(result.Result)));
}
- [TestMethod]
+ [Test()]
public void StringToThrowJsonRpcException()
{
string request = @"{method:'StringToThrowJsonRpcException',params:['some string'],id:1}";
- string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\"";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
- Assert.IsTrue(result.Result.StartsWith(expectedResult));
-
+ StringAssert.Contains("-2700", result.Result);
}
- [TestMethod]
+ [Test()]
public void ReturnsDateTime()
{
string request = @"{method:'ReturnsDateTime',params:[],id:1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
}
- [TestMethod]
+ [Test()]
public void ReturnsCustomRecursiveClass()
{
string request = @"{method:'ReturnsCustomRecursiveClass',params:[],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":{\"Nested1\":{\"Nested1\":null,\"Value1\":5},\"Value1\":10},\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void FloatToFloat()
{
string request = @"{method:'FloatToFloat',params:[0.123],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":0.123,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void IntToInt()
{
string request = @"{method:'IntToInt',params:[789],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void OptionalParamInt16()
- {
+ {
string request = @"{method:'TestOptionalParamInt16',params:[789],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
var result = JsonRpcProcessor.Process(request);
@@ -194,7 +240,7 @@ public void OptionalParamInt16()
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void OptionalParamInt16NoParam()
{
string request = @"{method:'TestOptionalParamInt16',params:[],id:1}";
@@ -205,41 +251,41 @@ public void OptionalParamInt16NoParam()
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void Int16ToInt16()
{
string request = @"{method:'Int16ToInt16',params:[789],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void Int32ToInt32()
{
string request = @"{method:'Int32ToInt32',params:[789],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void Int64ToInt64()
{
string request = @"{method:'Int64ToInt64',params:[78915984515564],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":78915984515564,\"id\":1}";
- var result = JsonRpcProcessor.Process(request);
+ var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamByteMissing()
{
string request = @"{method:'TestOptionalParambyte',params:[],id:1}";
@@ -249,7 +295,7 @@ public void TestOptionalParamByteMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbyteMissing()
{
string request = @"{method:'TestOptionalParamsbyte',params:[],id:1}";
@@ -259,7 +305,7 @@ public void TestOptionalParamSbyteMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShortMissing()
{
string request = @"{method:'TestOptionalParamshort',params:[],id:1}";
@@ -269,7 +315,7 @@ public void TestOptionalParamShortMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamintMissing()
{
string request = @"{method:'TestOptionalParamint',params:[],id:1}";
@@ -279,7 +325,7 @@ public void TestOptionalParamintMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLongMissing()
{
string request = @"{method:'TestOptionalParamlong',params:[],id:1}";
@@ -289,7 +335,7 @@ public void TestOptionalParamLongMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshortMissing()
{
string request = @"{method:'TestOptionalParamushort',params:[],id:1}";
@@ -299,7 +345,7 @@ public void TestOptionalParamUshortMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUintMissing()
{
string request = @"{method:'TestOptionalParamuint',params:[],id:1}";
@@ -309,7 +355,7 @@ public void TestOptionalParamUintMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlongMissing()
{
string request = @"{method:'TestOptionalParamulong',params:[],id:1}";
@@ -319,7 +365,7 @@ public void TestOptionalParamUlongMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloatMissing()
{
string request = @"{method:'TestOptionalParamfloat',params:[],id:1}";
@@ -329,7 +375,7 @@ public void TestOptionalParamFloatMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDoubleMissing()
{
string request = @"{method:'TestOptionalParamdouble',params:[],id:1}";
@@ -339,7 +385,7 @@ public void TestOptionalParamDoubleMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBoolMissing()
{
string request = @"{method:'TestOptionalParambool',params:[],id:1}";
@@ -349,7 +395,7 @@ public void TestOptionalParamBoolMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamCharMissing()
{
string request = @"{method:'TestOptionalParamchar',params:[],id:1}";
@@ -359,7 +405,7 @@ public void TestOptionalParamCharMissing()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimalMissing()
{
string request = @"{method:'TestOptionalParamdecimal',params:[],id:1}";
@@ -370,7 +416,7 @@ public void TestOptionalParamDecimalMissing()
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBytePresent()
{
string request = @"{method:'TestOptionalParambyte',params:[71],id:1}";
@@ -380,7 +426,7 @@ public void TestOptionalParamBytePresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbytePresent()
{
string request = @"{method:'TestOptionalParamsbyte',params:[71],id:1}";
@@ -390,7 +436,7 @@ public void TestOptionalParamSbytePresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShortPresent()
{
string request = @"{method:'TestOptionalParamshort',params:[71],id:1}";
@@ -400,7 +446,7 @@ public void TestOptionalParamShortPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamintPresent()
{
string request = @"{method:'TestOptionalParamint',params:[71],id:1}";
@@ -410,7 +456,7 @@ public void TestOptionalParamintPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLongPresent()
{
string request = @"{method:'TestOptionalParamlong',params:[71],id:1}";
@@ -420,7 +466,7 @@ public void TestOptionalParamLongPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshortPresent()
{
string request = @"{method:'TestOptionalParamushort',params:[71],id:1}";
@@ -430,7 +476,7 @@ public void TestOptionalParamUshortPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUintPresent()
{
string request = @"{method:'TestOptionalParamuint',params:[71],id:1}";
@@ -440,7 +486,7 @@ public void TestOptionalParamUintPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlongPresent()
{
string request = @"{method:'TestOptionalParamulong',params:[71],id:1}";
@@ -450,7 +496,7 @@ public void TestOptionalParamUlongPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloatPresent()
{
string request = @"{method:'TestOptionalParamfloat',params:[71],id:1}";
@@ -460,7 +506,7 @@ public void TestOptionalParamFloatPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDoublePresent()
{
string request = @"{method:'TestOptionalParamdouble',params:[71],id:1}";
@@ -470,7 +516,7 @@ public void TestOptionalParamDoublePresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBoolPresent()
{
string request = @"{method:'TestOptionalParambool',params:[false],id:1}";
@@ -480,17 +526,17 @@ public void TestOptionalParamBoolPresent()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamCharPresent()
{
- string request = @"{method:'TestOptionalParamchar',params:["+(int)'b'+"],id:1}";
+ string request = @"{method:'TestOptionalParamchar',params:[" + (int)'b' + "],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"b\",\"id\":1}";
var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimalPresent()
{
string request = @"{method:'TestOptionalParamdecimal',params:[71],id:1}";
@@ -501,7 +547,7 @@ public void TestOptionalParamDecimalPresent()
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBytePresentObjectSyntax()
{
string request = @"{method:'TestOptionalParambyte',params:{'input':71},id:1}";
@@ -511,7 +557,7 @@ public void TestOptionalParamBytePresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbytePresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamsbyte',params:{'input':71},id:1}";
@@ -521,7 +567,7 @@ public void TestOptionalParamSbytePresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShortPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamshort',params:{'input':71},id:1}";
@@ -531,7 +577,7 @@ public void TestOptionalParamShortPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamintPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamint',params:{'input':71},id:1}";
@@ -541,7 +587,7 @@ public void TestOptionalParamintPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLongPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamlong',params:{'input':71},id:1}";
@@ -551,7 +597,7 @@ public void TestOptionalParamLongPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshortPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamushort',params:{'input':71},id:1}";
@@ -561,7 +607,7 @@ public void TestOptionalParamUshortPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUintPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamuint',params:{'input':71},id:1}";
@@ -571,7 +617,7 @@ public void TestOptionalParamUintPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlongPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamulong',params:{'input':71},id:1}";
@@ -581,7 +627,7 @@ public void TestOptionalParamUlongPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloatPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamfloat',params:{'input':71},id:1}";
@@ -591,7 +637,7 @@ public void TestOptionalParamFloatPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDoublePresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamdouble',params:{'input':71},id:1}";
@@ -601,7 +647,7 @@ public void TestOptionalParamDoublePresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBoolPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParambool',params:{'input':false},id:1}";
@@ -611,17 +657,17 @@ public void TestOptionalParamBoolPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamCharPresentObjectSyntax()
{
- string request = @"{method:'TestOptionalParamchar',params:{'input':"+(int)'c'+"},id:1}";
+ string request = @"{method:'TestOptionalParamchar',params:{'input':" + (int)'c' + "},id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"c\",\"id\":1}";
var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimalPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamdecimal',params:{'input':71},id:1}";
@@ -632,7 +678,7 @@ public void TestOptionalParamDecimalPresentObjectSyntax()
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamByteMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParambyte',params:{},id:1}";
@@ -642,7 +688,7 @@ public void TestOptionalParamByteMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbyteMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamsbyte',params:{},id:1}";
@@ -652,7 +698,7 @@ public void TestOptionalParamSbyteMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShortMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamshort',params:{},id:1}";
@@ -662,7 +708,7 @@ public void TestOptionalParamShortMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamintMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamint',params:{},id:1}";
@@ -672,7 +718,7 @@ public void TestOptionalParamintMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLongMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamlong',params:{},id:1}";
@@ -682,7 +728,7 @@ public void TestOptionalParamLongMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshortMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamushort',params:{},id:1}";
@@ -692,7 +738,7 @@ public void TestOptionalParamUshortMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUintMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamuint',params:{},id:1}";
@@ -702,7 +748,7 @@ public void TestOptionalParamUintMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlongMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamulong',params:{},id:1}";
@@ -712,7 +758,7 @@ public void TestOptionalParamUlongMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloatMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamfloat',params:{},id:1}";
@@ -722,7 +768,7 @@ public void TestOptionalParamFloatMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDoubleMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamdouble',params:{},id:1}";
@@ -732,7 +778,7 @@ public void TestOptionalParamDoubleMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBoolMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParambool',params:{},id:1}";
@@ -742,7 +788,7 @@ public void TestOptionalParamBoolMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamCharMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamchar',params:{},id:1}";
@@ -752,7 +798,7 @@ public void TestOptionalParamCharMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimalMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamdecimal',params:{},id:1}";
@@ -763,7 +809,7 @@ public void TestOptionalParamDecimalMissingObjectSyntax()
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamByte_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123},id:1}";
@@ -773,7 +819,7 @@ public void TestOptionalParamByte_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbyte_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123},id:1}";
@@ -783,7 +829,7 @@ public void TestOptionalParamSbyte_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShort_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123},id:1}";
@@ -793,7 +839,7 @@ public void TestOptionalParamShort_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamint_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamint_2x',params:{input1:123},id:1}";
@@ -803,7 +849,7 @@ public void TestOptionalParamint_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLong_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123},id:1}";
@@ -813,7 +859,7 @@ public void TestOptionalParamLong_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshort_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123},id:1}";
@@ -823,7 +869,7 @@ public void TestOptionalParamUshort_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUint_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123},id:1}";
@@ -833,7 +879,7 @@ public void TestOptionalParamUint_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlong_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123},id:1}";
@@ -843,7 +889,7 @@ public void TestOptionalParamUlong_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloat_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123},id:1}";
@@ -853,7 +899,7 @@ public void TestOptionalParamFloat_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDouble_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123},id:1}";
@@ -863,7 +909,7 @@ public void TestOptionalParamDouble_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBool_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParambool_2x',params:{input1:123},id:1}";
@@ -873,7 +919,7 @@ public void TestOptionalParamBool_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamChar_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamchar_2x',params:{input1:123},id:1}";
@@ -883,7 +929,7 @@ public void TestOptionalParamChar_2ndMissingObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimal_2ndMissingObjectSyntax()
{
string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123},id:1}";
@@ -894,7 +940,7 @@ public void TestOptionalParamDecimal_2ndMissingObjectSyntax()
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamByte_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParambyte_2x',params:{input1:123, input2: 67},id:1}";
@@ -904,7 +950,7 @@ public void TestOptionalParamByte_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamByte_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParambyte_2x',params:[123, 67],id:1}";
@@ -914,7 +960,7 @@ public void TestOptionalParamByte_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamByte_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParambyte_2x',params:[123],id:1}";
@@ -924,7 +970,7 @@ public void TestOptionalParamByte_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbyte_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamsbyte_2x',params:{input1:123, input2: 97},id:1}";
@@ -934,7 +980,7 @@ public void TestOptionalParamSbyte_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbyte_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamsbyte_2x',params:[123, 98],id:1}";
@@ -944,7 +990,7 @@ public void TestOptionalParamSbyte_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamSbyte_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamsbyte_2x',params:[123],id:1}";
@@ -954,7 +1000,7 @@ public void TestOptionalParamSbyte_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShort_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamshort_2x',params:{input1:123, input2: 671},id:1}";
@@ -964,7 +1010,7 @@ public void TestOptionalParamShort_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShort_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamshort_2x',params:[123, 671],id:1}";
@@ -974,7 +1020,7 @@ public void TestOptionalParamShort_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamShort_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamshort_2x',params:[123],id:1}";
@@ -984,7 +1030,7 @@ public void TestOptionalParamShort_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamint_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamint_2x',params:{input1:123, input2: 671},id:1}";
@@ -994,7 +1040,7 @@ public void TestOptionalParamint_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamint_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamint_2x',params:[123, 671],id:1}";
@@ -1004,7 +1050,7 @@ public void TestOptionalParamint_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamint_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamint_2x',params:[123],id:1}";
@@ -1014,7 +1060,7 @@ public void TestOptionalParamint_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLong_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamlong_2x',params:{input1:123, input2: 671},id:1}";
@@ -1024,7 +1070,7 @@ public void TestOptionalParamLong_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLong_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamlong_2x',params:[123, 671],id:1}";
@@ -1034,7 +1080,7 @@ public void TestOptionalParamLong_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamLong_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamlong_2x',params:[123],id:1}";
@@ -1044,7 +1090,7 @@ public void TestOptionalParamLong_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshort_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamushort_2x',params:{input1:123, input2: 671},id:1}";
@@ -1054,7 +1100,7 @@ public void TestOptionalParamUshort_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshort_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamushort_2x',params:[123, 671],id:1}";
@@ -1064,7 +1110,7 @@ public void TestOptionalParamUshort_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUshort_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamushort_2x',params:[123],id:1}";
@@ -1074,7 +1120,7 @@ public void TestOptionalParamUshort_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUint_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamuint_2x',params:{input1:123, input2: 671},id:1}";
@@ -1084,7 +1130,7 @@ public void TestOptionalParamUint_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUint_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamuint_2x',params:[123, 671],id:1}";
@@ -1094,7 +1140,7 @@ public void TestOptionalParamUint_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUint_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamuint_2x',params:[123],id:1}";
@@ -1104,7 +1150,7 @@ public void TestOptionalParamUint_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlong_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamulong_2x',params:{input1:123, input2: 671},id:1}";
@@ -1114,7 +1160,7 @@ public void TestOptionalParamUlong_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlong_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamulong_2x',params:[123, 671],id:1}";
@@ -1124,7 +1170,7 @@ public void TestOptionalParamUlong_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamUlong_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamulong_2x',params:[123],id:1}";
@@ -1134,7 +1180,7 @@ public void TestOptionalParamUlong_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloat_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamfloat_2x',params:{input1:123, input2: 671},id:1}";
@@ -1144,7 +1190,7 @@ public void TestOptionalParamFloat_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloat_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamfloat_2x',params:[123, 671],id:1}";
@@ -1154,7 +1200,7 @@ public void TestOptionalParamFloat_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamFloat_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamfloat_2x',params:[123],id:1}";
@@ -1164,7 +1210,7 @@ public void TestOptionalParamFloat_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDouble_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamdouble_2x',params:{input1:123, input2: 671},id:1}";
@@ -1174,7 +1220,7 @@ public void TestOptionalParamDouble_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDouble_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamdouble_2x',params:[123, 671],id:1}";
@@ -1184,7 +1230,7 @@ public void TestOptionalParamDouble_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDouble_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamdouble_2x',params:[123],id:1}";
@@ -1194,7 +1240,7 @@ public void TestOptionalParamDouble_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBool_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParambool_2x',params:{input1:123, input2: 671},id:1}";
@@ -1204,7 +1250,7 @@ public void TestOptionalParamBool_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBool_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParambool_2x',params:[true, false],id:1}";
@@ -1214,7 +1260,7 @@ public void TestOptionalParamBool_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamBool_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParambool_2x',params:[123],id:1}";
@@ -1224,7 +1270,7 @@ public void TestOptionalParamBool_2ndMissingArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamChar_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamchar_2x',params:{'input1':" + (int)'c' + ", 'input2':" + (int)'d' + "},id:1}";
@@ -1234,7 +1280,7 @@ public void TestOptionalParamChar_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamChar_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + ", " + (int)'d' + "],id:1}";
@@ -1244,17 +1290,17 @@ public void TestOptionalParamChar_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamChar_2ndMissingArraySyntax()
{
- string request = @"{method:'TestOptionalParamchar_2x',params:["+(int)'c'+"],id:1}";
+ string request = @"{method:'TestOptionalParamchar_2x',params:[" + (int)'c' + "],id:1}";
string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}";
var result = JsonRpcProcessor.Process(request);
result.Wait();
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimal_2ndPresentObjectSyntax()
{
string request = @"{method:'TestOptionalParamdecimal_2x',params:{input1:123, input2: 671},id:1}";
@@ -1264,7 +1310,7 @@ public void TestOptionalParamDecimal_2ndPresentObjectSyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimal_2ndPresentArraySyntax()
{
string request = @"{method:'TestOptionalParamdecimal_2x',params:[123, 671],id:1}";
@@ -1274,7 +1320,7 @@ public void TestOptionalParamDecimal_2ndPresentArraySyntax()
Assert.IsFalse(result.Result.Contains("error"));
Assert.AreEqual(expectedResult, result.Result);
}
- [TestMethod]
+ [Test()]
public void TestOptionalParamDecimal_2ndMissingArraySyntax()
{
string request = @"{method:'TestOptionalParamdecimal_2x',params:[123],id:1}";
@@ -1285,6 +1331,664 @@ public void TestOptionalParamDecimal_2ndMissingArraySyntax()
Assert.AreEqual(expectedResult, result.Result);
}
+ [Test()]
+ public void TestOptionalParametersStrings_BothMissing()
+ {
+ string request = @"{method:'TestOptionalParameters_Strings',params:[],id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[null,null],\"id\":1}";
+
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsFalse(result.Result.Contains("error"));
+ Assert.AreEqual(expectedResult, result.Result);
+ }
+
+ [Test()]
+ public void TestOptionalParametersStrings_SecondMissing()
+ {
+ string request = @"{method:'TestOptionalParameters_Strings',params:['first'],id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",null],\"id\":1}";
+
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsFalse(result.Result.Contains("error"));
+ Assert.AreEqual(expectedResult, result.Result);
+ }
+
+ [Test()]
+ public void TestOptionalParametersStrings_BothExists()
+ {
+ string request = @"{method:'TestOptionalParameters_Strings',params:['first','second'],id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":[\"first\",\"second\"],\"id\":1}";
+
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsFalse(result.Result.Contains("error"));
+ Assert.AreEqual(expectedResult, result.Result);
+ }
+
+ [Test()]
+ public void TestOptionalParametersBoolsAndStrings()
+ {
+ string request =
+ "{\"jsonrpc\":\"2.0\",\"method\":\"TestOptionalParametersBoolsAndStrings\",\"params\":{\"input1\":\"murkel\"},\"Id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsFalse(result.Result.Contains("error"));
+ Assert.AreEqual(expectedResult, result.Result);
+ }
+
+ [TestCase("{method:\"TestDifferentOptionalParameters\",params:{location:\"loc1\", uid:\"abc123\", wavelengths: [0.0], traces: [0.0]},id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"this is the requested measurement\",\"id\":1}")]
+ [TestCase("{method:\"TestDifferentOptionalParameters\",params:{uid:\"abc123\", wavelengths: [0.0], traces: [0.0]},id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"this is the requested measurement\",\"id\":1}")]
+ [TestCase("{method:\"TestDifferentOptionalParameters\",params:{location:\"loc1\", uid:\"abc123\", traces: [0.0]},id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"this is the requested measurement\",\"id\":1}")]
+ [TestCase("{method:\"TestDifferentOptionalParameters\",params:{location:\"loc1\", uid:\"abc123\", wavelengths: [0.0]},id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"this is the requested measurement\",\"id\":1}")]
+ [TestCase("{method:\"TestDifferentOptionalParameters\",params:{uid:\"abc123\", wavelengths: [0.0]},id:1}", ExpectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"this is the requested measurement\",\"id\":1}")]
+ public string TestDifferentOptionalParametersNamedWorking(string request)
+ {
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ return result.Result;
+ }
+
+ [Test()]
+ public void TestBatchResultWrongRequests()
+ {
+ string request = @"[{},{""jsonrpc"":""2.0"",""id"":4}]";
+
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+
+ Assert.IsTrue(Regex.IsMatch(result.Result, @"\[(\{.*""error"":.*?,""id"":.*?\}),(\{.*""error"":.*?,""id"":.*?\})\]"), "Should have two errors.");
+ }
+
+ [Test()]
+ public void TestBatchResultMultipleMethodCallsNotificationAtLast()
+ {
+ string request =
+ @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}]";
+
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+
+ Assert.IsFalse(result.Result.EndsWith(@",]"), "result.Result.EndsWith(@',]')");
+
+ }
+
+ [Test()]
+ public void TestEmptyBatchResult()
+ {
+ var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}";
+ var result = JsonRpcProcessor.Process(secondRequest);
+ result.Wait();
+
+ Assert.IsTrue(string.IsNullOrEmpty(result.Result));
+ }
+
+
+ [Test()]
+ public void TestNotificationVoidResult()
+ {
+ var secondRequest = @"{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""], ""id"":73}";
+ var result = JsonRpcProcessor.Process(secondRequest);
+ result.Wait();
+ Console.WriteLine(result.Result);
+ Assert.IsTrue(result.Result.Contains("result"), "Json Rpc 2.0 Spec - 'result' - This member is REQUIRED on success. A function that returns void should have the result property included even though the value may be null.");
+ }
+
+ [Test()]
+ public void TestLeftOutParams()
+ {
+ var request =
+ @"{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""id"":1}";
+
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+
+ Assert.IsFalse(result.Result.Contains(@"error"":{""code"":-32602"), @"According to JSON-RPC 2.0 the ""params"" member MAY be omitted.");
+ }
+
+ [Test()]
+ public void TestMultipleResults()
+ {
+ var result =
+ JsonRpcProcessor.Process(
+ @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]");
+ result.Wait();
+
+ Assert.IsTrue(result.Result.EndsWith("]"));
+ }
+ [Test()]
+ public void TestSingleResultBatch()
+ {
+ var result =
+ JsonRpcProcessor.Process(@"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]");
+ result.Wait();
+ Assert.IsFalse(result.Result.EndsWith("]"));
+ }
+
+ class PreProcessHandlerLocal
+ {
+ public JsonRequest rpc = null;
+ public object context = null;
+ public int run = 0;
+
+ public JsonRpcException PreProcess(JsonRequest rpc, object context)
+ {
+ run++;
+
+ this.rpc = rpc;
+ this.context = context;
+
+ return null;
+ }
+ }
+
+ [Test()]
+ public void TestPreProcessor()
+ {
+ try {
+ PreProcessHandlerLocal handler = new PreProcessHandlerLocal();
+ Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess));
+ string request = @"{method:'TestPreProcessor',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.Null(handler.context, "Context should be null");
+ } finally {
+ Config.SetPreProcessHandler(null);
+ }
+
+ }
+
+ [Test()]
+ public void TestPreProcessorThrowsJsonRPCException()
+ {
+ try
+ {
+ PreProcessHandlerLocal handler = new PreProcessHandlerLocal();
+ Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess));
+ string request = @"{method:'TestPreProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPreProcessorThrowsException()
+ {
+ try
+ {
+ PreProcessHandlerLocal handler = new PreProcessHandlerLocal();
+ Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess));
+ string request = @"{method:'TestPreProcessorThrowsException',params:{inputValue:'some string'},id:1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ StringAssert.Contains("-32603", result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPreProcessorSetsException()
+ {
+ try
+ {
+ PreProcessHandlerLocal handler = new PreProcessHandlerLocal();
+ Config.SetPreProcessHandler(new PreProcessHandler(handler.PreProcess));
+ string request = @"{method:'TestPreProcessorSetsException',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPreProcessOnSession()
+ {
+ var sessionId = "my session";
+ var h = JsonRpc.Handler.GetSessionHandler(sessionId);
+ PreProcessHandlerLocal preHandler = new PreProcessHandlerLocal();
+ h.SetPreProcessHandler(new PreProcessHandler(preHandler.PreProcess));
+
+ var metadata = new System.Collections.Generic.List> {
+ Tuple.Create ("sooper", typeof(string)),
+ Tuple.Create ("returns", typeof(string))
+ }.ToDictionary(x => x.Item1, x => x.Item2);
+ h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(),new Func(x => "workie ... " + x));
+
+ string request = @"{method:'workie',params:{'sooper':'good'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}";
+ string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}";
+ var result = JsonRpcProcessor.Process(sessionId, request);
+ result.Wait();
+
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult);
+ Assert.IsTrue(JToken.DeepEquals(expected1, actual1));
+ Assert.AreEqual(1, preHandler.run);
+
+ h.Destroy();
+
+ var result2 = JsonRpcProcessor.Process(sessionId, request);
+ result2.Wait();
+
+ Assert.AreEqual(1, preHandler.run);
+ Assert.IsTrue(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result)));
+ }
+
+ class PostProcessHandlerLocal
+ {
+ public JsonRequest rpc = null;
+ public JsonResponse response = null;
+ public object context = null;
+ public int run = 0;
+ private bool changeResponse_;
+
+ public PostProcessHandlerLocal(bool changeResponse)
+ {
+ changeResponse_ = changeResponse;
+ }
+
+ public JsonRpcException PostProcess(JsonRequest rpc, JsonResponse response, object context)
+ {
+ run++;
+
+ this.rpc = rpc;
+ this.response = response;
+ this.context = context;
+
+ if (changeResponse_)
+ {
+ return new JsonRpcException(-123, "Test error", null);
+ }
+ return null;
+ }
+ }
+
+ [Test()]
+ public void TestPostProcessor()
+ {
+ try
+ {
+ PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false);
+ Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess));
+ string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"Success!\",\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run, "Expect number of times run 1");
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.NotNull(handler.response, "response should not be null");
+ Assert.AreEqual("Success!", (string)handler.response.Result);
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPostProcessorThrowsJsonRPCException()
+ {
+ try
+ {
+ PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false);
+ Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess));
+ string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27000,\"message\":\"Just some testing\",\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.NotNull(handler.response, "response should not be null");
+ Assert.Null(handler.response.Result, "Result should be null");
+ Assert.NotNull(handler.response.Error, "Error should not be null");
+ Assert.AreEqual(-27000, handler.response.Error.code, "Error code mismatch");
+ Assert.AreEqual("Just some testing", handler.response.Error.message, "Error message mismatch");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPostProcessorThrowsException()
+ {
+ try
+ {
+ PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false);
+ Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess));
+ string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ StringAssert.Contains("-32603", result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.NotNull(handler.response, "response should not be null");
+ Assert.Null(handler.response.Result, "Result should be null");
+ Assert.NotNull(handler.response.Error, "Error should not be null");
+ Assert.AreEqual(-32603, handler.response.Error.code, "Error code mismatch");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPostProcessorSetsException()
+ {
+ try
+ {
+ PostProcessHandlerLocal handler = new PostProcessHandlerLocal(false);
+ Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess));
+ string request = @"{method:'TestPostProcessorSetsException',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-27001,\"message\":\"This exception was thrown using: JsonRpcContext.SetException()\",\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+
+ [Test()]
+ public void TestPostProcessorChangesReturn()
+ {
+ try
+ {
+ PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true);
+ Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess));
+ string request = @"{method:'TestPostProcessor',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.AreEqual(1, handler.run, "Expect number of times run 1");
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.NotNull(handler.response, "response should not be null");
+ Assert.AreEqual("Success!", (string)handler.response.Result);
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPostProcessorThrowsJsonRPCExceptionChangesReturn()
+ {
+ try
+ {
+ PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true);
+ Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess));
+ string request = @"{method:'TestPostProcessorThrowsJsonRPCException',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-123,\"message\":\"Test error\",\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.NotNull(handler.response, "response should not be null");
+ Assert.Null(handler.response.Result, "Result should be null");
+ Assert.NotNull(handler.response.Error, "Error should not be null");
+ Assert.AreEqual(-27000, handler.response.Error.code, "Error code mismatch");
+ Assert.AreEqual("Just some testing", handler.response.Error.message, "Error message mismatch");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPostProcessorThrowsExceptionChangesReturn()
+ {
+ try
+ {
+ PostProcessHandlerLocal handler = new PostProcessHandlerLocal(true);
+ Config.SetPostProcessHandler(new PostProcessHandler(handler.PostProcess));
+ string request = @"{method:'TestPostProcessorThrowsException',params:{inputValue:'some string'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Test error\",\"code\":-123,\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.AreEqual(1, handler.run);
+ Assert.NotNull(handler.rpc, "RPC should not be null");
+ Assert.NotNull(handler.response, "response should not be null");
+ Assert.Null(handler.response.Result, "Result should be null");
+ Assert.NotNull(handler.response.Error, "Error should not be null");
+ Assert.AreEqual(-32603, handler.response.Error.code, "Error code mismatch");
+ Assert.Null(handler.context, "Context should be null");
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Test()]
+ public void TestPostProcessOnSession()
+ {
+ var sessionId = "my first session";
+ var h = JsonRpc.Handler.GetSessionHandler(sessionId);
+ PostProcessHandlerLocal postHandler = new PostProcessHandlerLocal(false);
+ h.SetPostProcessHandler(new PostProcessHandler(postHandler.PostProcess));
+
+ var metadata = new System.Collections.Generic.List> {
+ Tuple.Create ("sooper", typeof(string)),
+ Tuple.Create ("returns", typeof(string))
+ }.ToDictionary(x => x.Item1, x => x.Item2);
+ h.RegisterFuction("workie", metadata, new System.Collections.Generic.Dictionary(), new Func(x => "workie ... " + x));
+
+ string request = @"{method:'workie',params:{'sooper':'good'},id:1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"workie ... good\",\"id\":1}";
+ string expectedResultAfterDestroy = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Method not found\",\"code\":-32601,\"data\":\"The method does not exist / is not available.\"},\"id\":1}";
+ var result = JsonRpcProcessor.Process(sessionId, request);
+ result.Wait();
+
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult);
+ Assert.IsTrue(JToken.DeepEquals(expected1, actual1));
+ Assert.AreEqual(1, postHandler.run);
+
+ h.Destroy();
+
+ var result2 = JsonRpcProcessor.Process(sessionId, request);
+ result2.Wait();
+
+ Assert.AreEqual(1, postHandler.run);
+ Assert.IsTrue(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result)));
+ }
+
+ [Test()]
+ public void TestExtraParameters()
+ {
+ string request = @"{method:'ReturnsDateTime',params:{extra:'mytext'},id:1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsTrue(result.Result.Contains("error"));
+ Assert.IsTrue(result.Result.Contains("\"code\":-32602"));
+ }
+
+ [Test()]
+ public void TestExtraPositionalParameters()
+ {
+ string request = @"{method:'ReturnsDateTime',params:[1,2,'mytext'],id:1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsTrue(result.Result.Contains("error"));
+ Assert.IsTrue(result.Result.Contains("\"code\":-32602"));
+ }
+
+ [Test()]
+ public void TestCustomParameterName()
+ {
+ Func request = (string paramName) => String.Format("{{method:'TestCustomParameterName',params:{{ {0}:'some string'}},id:1}}", paramName);
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+ // Check custom param name specified in attribute works
+ var result = JsonRpcProcessor.Process(request("myCustomParameter"));
+ result.Wait();
+ Assert.AreEqual(JObject.Parse(expectedResult), JObject.Parse(result.Result));
+ // Check method can't be used with its actual parameter name
+ result = JsonRpcProcessor.Process(request("arg"));
+ result.Wait();
+ StringAssert.Contains("-32602", result.Result); // check for 'invalid params' error code
+ }
+
+ [Test()]
+ public void TestCustomParameterWithNoSpecificName()
+ {
+ Func request = (string paramName) => String.Format("{{method:'TestCustomParameterWithNoSpecificName',params:{{ {0}:'some string'}},id:1}}", paramName);
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+ // Check method can be used with its parameter name
+ var result = JsonRpcProcessor.Process(request("arg"));
+ result.Wait();
+ Assert.AreEqual(JObject.Parse(expectedResult), JObject.Parse(result.Result));
+ }
+
+ [Test]
+ public void TestNestedReturnType()
+ {
+ var request = @"{""jsonrpc"":""2.0"",""method"":""TestNestedReturnType"",""id"":1}";
+ var expected = @"{""jsonrpc"":""2.0"",""result"":{""NodeId"":1,""Leafs"":[{""NodeId"":2,""Leafs"":[]},{""NodeId"":3,""Leafs"":[]}]},""id"":1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.AreEqual(expected, result.Result);
+ }
+
+ [Test()]
+ public void TestWrongParamType()
+ {
+ string request = @"{method:'TestOptionalParamdouble',params:{input:'mytext'},id:1}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsTrue(result.Result.Contains("error"));
+ Assert.IsTrue(result.Result.Contains("\"code\":-32603"));
+ }
+
+ [Test()]
+ public void TestWrongIdType()
+ {
+ string request = @"{method:'TestOptionalParamdouble',params:{input:5},id:{what:4,that:3}}";
+ var result = JsonRpcProcessor.Process(request);
+ result.Wait();
+ Assert.IsTrue(result.Result.Contains("error"));
+ Assert.IsTrue(result.Result.Contains("\"code\":-32600"));
+ }
+
+ private static void AssertJsonAreEqual(string expectedJson, string actualJson)
+ {
+ Newtonsoft.Json.Linq.JObject expected = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(expectedJson);
+ Newtonsoft.Json.Linq.JObject actual = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(actualJson);
+ AssertJsonAreEqual(expected, actual, "root");
+ }
+
+ private static void AssertJsonAreEqual(JToken expectedJson, JToken actualJson, string path)
+ {
+ Assert.AreEqual(expectedJson.GetType(), actualJson.GetType(), "Type mismatch at " + path);
+ if (expectedJson is JObject)
+ {
+ AssertJsonAreEqual((JObject)expectedJson, (JObject)actualJson, path);
+ } else if (expectedJson is JObject)
+ {
+ AssertJsonAreEqual((JArray)expectedJson, (JArray)actualJson, path);
+ } else if (expectedJson is JValue)
+ {
+ AssertJsonAreEqual((JValue)expectedJson, (JValue)actualJson, path);
+ } else
+ {
+ throw new Exception("I don't know how to handle " + expectedJson.GetType().ToString());
+ }
+ }
+
+ private static void AssertJsonAreEqual(JObject expectedJson, JObject actualJson, string path)
+ {
+ Console.WriteLine("expected: {0}", expectedJson);
+ Console.WriteLine("actual : {0}", actualJson);
+ Assert.AreEqual(expectedJson.Count, actualJson.Count, "Count of json object at " + path);
+ for (var expectedElementsEnumerator = expectedJson.GetEnumerator(); expectedElementsEnumerator.MoveNext(); )
+ {
+ JToken actualElement = null;
+ Assert.IsTrue(actualJson.TryGetValue(expectedElementsEnumerator.Current.Key, out actualElement), "Couldn't find " + path + "[" + expectedElementsEnumerator.Current.Key + "]");
+ AssertJsonAreEqual(expectedElementsEnumerator.Current.Value, actualElement, path + "[" + expectedElementsEnumerator.Current.Key + "]");
+ }
+ }
+
+ private static void AssertJsonAreEqual(JArray expectedJson, JArray actualJson, string path)
+ {
+ Assert.AreEqual(expectedJson.Count, actualJson.Count, "Count of json array at " + path);
+ for (int jsonIndex = 0; jsonIndex < expectedJson.Count; jsonIndex++)
+ {
+ AssertJsonAreEqual(expectedJson[jsonIndex], actualJson[jsonIndex], path + "[" + jsonIndex.ToString() + "]");
+ }
+ }
+
+ private static void AssertJsonAreEqual(JValue expectedJson, JValue actualJson, string path)
+ {
+ Assert.AreEqual(expectedJson.Type, actualJson.Type, path);
+ switch (expectedJson.Type)
+ {
+ case JTokenType.Boolean:
+ Assert.AreEqual((bool)expectedJson.Value, (bool)actualJson.Value, path);
+ break;
+ case JTokenType.Integer:
+ Assert.AreEqual((System.Int64)expectedJson.Value, (System.Int64)actualJson.Value, path);
+ break;
+ case JTokenType.String:
+ Assert.AreEqual((string)expectedJson.Value, (string)actualJson.Value, path);
+ break;
+ case JTokenType.Null:
+ //Not used
+ break;
+ default:
+ throw new Exception("I don't know how to handle type " + expectedJson.Type.ToString());
+ }
+ }
}
}
+
diff --git a/AustinHarris.JsonRpcTest/service.cs b/AustinHarris.JsonRpcTestN/service.cs
similarity index 67%
rename from AustinHarris.JsonRpcTest/service.cs
rename to AustinHarris.JsonRpcTestN/service.cs
index cfa256e..b34d957 100644
--- a/AustinHarris.JsonRpcTest/service.cs
+++ b/AustinHarris.JsonRpcTestN/service.cs
@@ -1,11 +1,19 @@
using AustinHarris.JsonRpc;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Text;
-namespace UnitTests
+namespace AustinHarris.JsonRpcTestN
{
+ public class TreeNode
+ {
+ public int NodeId { get; set; }
+
+ public IList Leafs { get; set; }
+ }
+
public class CalculatorService : JsonRpcService
{
[JsonRpcMethod]
@@ -42,7 +50,6 @@ private List StringToListOfString(string input)
private List StringToThrowingException(string input)
{
throw new Exception("Throwing Exception");
- return new List() { "one", "two", "three", input };
}
public class CustomString
@@ -72,6 +79,19 @@ private string devideByZero(string s)
return s + j / i;
}
+
+ [JsonRpcMethod]
+ private bool TestCustomParameterName([JsonRpcParam("myCustomParameter")] string arg)
+ {
+ return true;
+ }
+
+ [JsonRpcMethod]
+ private bool TestCustomParameterWithNoSpecificName([JsonRpcParam] string arg)
+ {
+ return true;
+ }
+
[JsonRpcMethod]
private string StringToRefException(string s, ref JsonRpcException refException)
{
@@ -283,7 +303,98 @@ public decimal TestOptionalParamdecimal_2x(decimal input1, decimal input2 = 987)
{
return input2;
}
+ [JsonRpcMethod]
+ private IList TestOptionalParameters_Strings(string input1 = null, string input2 = null)
+ {
+ return new List()
+ {
+ input1,
+ input2
+ };
+ }
+
+ [JsonRpcMethod]
+ public bool TestOptionalParametersBoolsAndStrings(string input1, bool input2 = true, string input3 = "")
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public void Notify(string message)
+ {
+ Trace.WriteLine(string.Format("Notified about: {0}", message));
+ }
+
+ [JsonRpcMethod]
+ public string TestPreProcessor(string inputValue)
+ {
+ return "Success!";
+ }
+
+ [JsonRpcMethod]
+ public string TestPreProcessorThrowsJsonRPCException(string inputValue)
+ {
+ throw new JsonRpcException(-27000, "Just some testing", null);
+ }
+
+ [JsonRpcMethod]
+ public string TestPreProcessorThrowsException(string inputValue)
+ {
+ throw new Exception("TestException");
+ }
+
+ [JsonRpcMethod]
+ public string TestPreProcessorSetsException(string inputValue)
+ {
+ JsonRpcContext.SetException(new JsonRpcException(-27000, "This exception was thrown using: JsonRpcContext.SetException()", null));
+ return null;
+ }
+
+ [JsonRpcMethod]
+ public string TestPostProcessor(string inputValue)
+ {
+ return "Success!";
+ }
+
+ [JsonRpcMethod]
+ public string TestPostProcessorThrowsJsonRPCException(string inputValue)
+ {
+ throw new JsonRpcException(-27000, "Just some testing", null);
+ }
+
+ [JsonRpcMethod]
+ public string TestPostProcessorThrowsException(string inputValue)
+ {
+ throw new Exception("TestException");
+ }
+
+ [JsonRpcMethod]
+ public string TestPostProcessorSetsException(string inputValue)
+ {
+ JsonRpcContext.SetException(new JsonRpcException(-27001, "This exception was thrown using: JsonRpcContext.SetException()", null));
+ return null;
+ }
+
+ [JsonRpcMethod]
+ public TreeNode TestNestedReturnType()
+ {
+ return new TreeNode
+ {
+ NodeId = 1,
+ Leafs =
+ new[]
+ {
+ new TreeNode {NodeId = 2, Leafs = new List()},
+ new TreeNode {NodeId = 3, Leafs = new List()}
+ }
+ };
+ }
+
+ [JsonRpcMethod]
+ private string TestDifferentOptionalParameters(string uid, string location = null, List traces = null, List wavelengths = null)
+ {
+ return "this is the requested measurement";
+ }
}
}
diff --git a/Json-Rpc/Attributes.cs b/Json-Rpc/Attributes.cs
index dd78282..1592511 100644
--- a/Json-Rpc/Attributes.cs
+++ b/Json-Rpc/Attributes.cs
@@ -24,4 +24,27 @@ public string JsonMethodName
get { return jsonMethodName; }
}
}
+
+ ///
+ /// Used to assign JsonRpc parameter name to method argument.
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)]
+ public sealed class JsonRpcParamAttribute : Attribute
+ {
+ readonly string jsonParamName;
+
+ ///
+ /// Used to assign JsonRpc parameter name to method argument.
+ ///
+ /// Lets you specify the parameter name as it will be referred to by JsonRpc.
+ public JsonRpcParamAttribute(string jsonParamName = "")
+ {
+ this.jsonParamName = jsonParamName;
+ }
+
+ public string JsonParamName
+ {
+ get { return jsonParamName; }
+ }
+ }
}
diff --git a/Json-Rpc/AustinHarris.JsonRpc.csproj b/Json-Rpc/AustinHarris.JsonRpc.csproj
index 3f7907f..f6a680d 100644
--- a/Json-Rpc/AustinHarris.JsonRpc.csproj
+++ b/Json-Rpc/AustinHarris.JsonRpc.csproj
@@ -1,89 +1,27 @@
-
-
-
- Debug
- x86
- 8.0.30703
- 2.0
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}
- Library
- Properties
- AustinHarris.JsonRpc
- AustinHarris.JsonRpc
- v4.0
-
-
- 512
- SAK
- SAK
- SAK
- SAK
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- false
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- false
-
-
-
-
-
- AnyCPU
- bin\Debug\
- TRACE;DEBUG
-
-
- AnyCPU
- bin\Release\
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- False
- ..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll
-
-
-
-
-
-
-
-
+
+
+
+ Austin Harris
+ Json-Rpc.Net Core
+ Core functionality for JsonRpc.Net
+ 1.2.3
+ $(VersionSuffix)
+ Austin Harris
+ https://github.com/Astn/JSON-RPC.NET
+ https://raw.githubusercontent.com/Astn/JSON-RPC.NET/master/LICENSE
+
+ Improves support for optional parameters - @HoMS1987 https://github.com/HoMS1987
+ Fixes protocol validation of the ID property - @pedrolcl https://github.com/pedrolcl
+ DotNet Core support - @astn https://github.com/astn
+
+ netstandard2.0;netstandard2.1;netcoreapp3.1
+ true
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Json-Rpc/AustinHarris.JsonRpc.nuspec b/Json-Rpc/AustinHarris.JsonRpc.nuspec
index 296958d..ad36f62 100644
--- a/Json-Rpc/AustinHarris.JsonRpc.nuspec
+++ b/Json-Rpc/AustinHarris.JsonRpc.nuspec
@@ -3,21 +3,21 @@
AustinHarris.JsonRpc
$version$
- JSON-RPC.NET Core
+ JSON-RPC.NET
Austin Harris
- http://jsonrpc2.codeplex.com/license
- http://jsonrpc2.codeplex.com/
+ https://raw.githubusercontent.com/Astn/JSON-RPC.NET/master/LICENSE
+ https://github.com/Astn/JSON-RPC.NET
http://download-codeplex.sec.s-msft.com/Download?ProjectName=jsonrpc2&DownloadId=487107
false
- Core functionality for JsonRpc.Net
- JSON-RPC.Net is a high performance Json-Rpc 2.0 server, leveraging the popular JSON.NET library. Host in ASP.NET, also supports sockets and pipes, oh my!
- Added support for optional params. Improved task usage / performance. Better float handling for non en-US cultures. Can now override ParseErrors. Can now unregister handlers. Using lower-cased property names during serialization. Many thanks to raistlinthewiz.
+ The fastest .Net JSON RPC Server
+ JSON-RPC.Net is a high performance Json-Rpc 2.0 server, leveraging the popular JSON.NET library. Easily create a JSON RPC server for your Angular javascript apps, also supports sockets and pipes, oh my!
+ Optional JsonSerializer Settings - @hovi. ProcessSync is now public - @astn
en-US
- Json Rpc Json-Rpc.Net Json-Rpc JsonRpc Json.net
+ fast json rpc server socket javascript json-rpc.net json-rpc jsonrpc json.net web services webapi service angular server angularjs
-
+
diff --git a/Json-Rpc/Config.cs b/Json-Rpc/Config.cs
index 5c2c1e7..9e6692e 100644
--- a/Json-Rpc/Config.cs
+++ b/Json-Rpc/Config.cs
@@ -13,6 +13,16 @@ namespace AustinHarris.JsonRpc
/// The context associated with this request
/// Any non-null result causes the operation to be aborted, and the JsonRpcException is returned to the caller.
public delegate JsonRpcException PreProcessHandler(JsonRequest request, object context);
+ ///
+ /// The PostProcessHandler is called after the response has been created and prior to returning the data to the caller.
+ /// If any non-null result is returned from the PostProcessHandler, the current return value is discared and the new return value used
+ /// in preference.
+ ///
+ /// The jsonRpc Request that has been processed.
+ /// The jsonRpc Response that has been created.
+ /// The context associated with this request/response pair
+ /// Any non-null result causes the result to be discarded and the JsonRpcException is returned to the caller.
+ public delegate JsonRpcException PostProcessHandler(JsonRequest request, JsonResponse response, object context);
///
/// Global configurations for JsonRpc
@@ -28,6 +38,15 @@ public static void SetPreProcessHandler(PreProcessHandler handler)
Handler.DefaultHandler.SetPreProcessHandler(handler);
}
+ ///
+ /// Sets the the PostProcessing Handler on the default session.
+ ///
+ ///
+ public static void SetPostProcessHandler(PostProcessHandler handler)
+ {
+ Handler.DefaultHandler.SetPostProcessHandler(handler);
+ }
+
///
/// Sets the PreProcessing Handler on a specific session
///
diff --git a/Json-Rpc/Handler.cs b/Json-Rpc/Handler.cs
index 2b461d2..095bacb 100644
--- a/Json-Rpc/Handler.cs
+++ b/Json-Rpc/Handler.cs
@@ -8,15 +8,21 @@
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Collections.Concurrent;
-using Newtonsoft.Json.Linq;
+ using Newtonsoft.Json.Linq;
+ using System.Threading;
public class Handler
{
#region Members
-
- //private static Handler current;
- private static ConcurrentDictionary _sessionHandlers;
- private static string _defaultSessionId;
+ private const string Name_of_JSONRPCEXCEPTION = "JsonRpcException&";
+ private static int _sessionHandlerMasterVersion = 1;
+ [ThreadStatic]
+ private static Dictionary _sessionHandlersLocal;
+ [ThreadStatic]
+ private static int _sessionHandlerLocalVersion = 0;
+ private static ConcurrentDictionary _sessionHandlersMaster;
+
+ private static volatile string _defaultSessionId;
#endregion
#region Constructors
@@ -25,15 +31,14 @@ static Handler()
{
//current = new Handler(Guid.NewGuid().ToString());
_defaultSessionId = Guid.NewGuid().ToString();
- _sessionHandlers = new ConcurrentDictionary();
- _sessionHandlers[_defaultSessionId]= new Handler(_defaultSessionId);
+ _sessionHandlersMaster = new ConcurrentDictionary();
+ _sessionHandlersMaster[_defaultSessionId] = new Handler(_defaultSessionId);
}
private Handler(string sessionId)
{
SessionId = sessionId;
this.MetaData = new SMD();
- this.Handlers = new Dictionary();
}
#endregion
@@ -53,9 +58,19 @@ private Handler(string sessionId)
///
public static Handler GetSessionHandler(string sessionId)
{
- return _sessionHandlers.GetOrAdd(sessionId, new Handler(sessionId));
+ if (_sessionHandlerMasterVersion != _sessionHandlerLocalVersion)
+ {
+ _sessionHandlersLocal = new Dictionary(_sessionHandlersMaster);
+ _sessionHandlerLocalVersion = _sessionHandlerMasterVersion;
+ }
+ if (_sessionHandlersLocal.ContainsKey(sessionId))
+ {
+ return _sessionHandlersLocal[sessionId];
+ }
+ Interlocked.Increment(ref _sessionHandlerMasterVersion);
+ return _sessionHandlersMaster.GetOrAdd(sessionId, new Handler(sessionId));
}
-
+
///
/// gets the default session
///
@@ -72,8 +87,8 @@ public static Handler GetSessionHandler()
public static void DestroySession(string sessionId)
{
Handler h;
- _sessionHandlers.TryRemove(sessionId,out h);
- h.Handlers.Clear();
+ _sessionHandlersMaster.TryRemove(sessionId, out h);
+ Interlocked.Increment(ref _sessionHandlerMasterVersion);
h.MetaData.Services.Clear();
}
///
@@ -92,10 +107,7 @@ public void Destroy()
///
/// The sessionID of this Handler
///
- public string SessionId { get; private set; }
-
- private static ConcurrentDictionary RpcContexts = new ConcurrentDictionary();
- private static ConcurrentDictionary RpcExceptions = new ConcurrentDictionary();
+ public string SessionId { get; private set; }
///
/// Provides access to a context specific to each JsonRpc method invocation.
@@ -104,43 +116,31 @@ public void Destroy()
///
public static object RpcContext()
{
- if (Task.CurrentId == null)
- return null;
-
- if (RpcContexts.ContainsKey(Task.CurrentId.Value) == false)
- return null;
-
- return RpcContexts[Task.CurrentId.Value];
+ return __currentRpcContext;
}
+ [ThreadStatic]
+ static JsonRpcException __currentRpcException;
///
/// Allows you to set the exception used in in the JsonRpc response.
- /// Warning: Must be called from within the execution context of the jsonRpc method.
+ /// Warning: Must be called from the same thread as the jsonRpc method.
///
///
public static void RpcSetException(JsonRpcException exception)
{
- if (Task.CurrentId != null)
- RpcExceptions[Task.CurrentId.Value] = exception;
- else
- throw new InvalidOperationException("This method is only valid when used within the context of a method marked as a JsonRpcMethod, and that method must of been invoked by the JsonRpc Handler.");
+ __currentRpcException = exception;
}
-
- private void RemoveRpcException()
+ public static JsonRpcException RpcGetAndRemoveRpcException()
{
- if (Task.CurrentId != null)
- {
- var id = Task.CurrentId.Value;
- RpcExceptions[id] = null;
- JsonRpcException va;
- RpcExceptions.TryRemove(id, out va);
- }
+ var ex = __currentRpcException;
+ __currentRpcException = null ;
+ return ex;
}
private AustinHarris.JsonRpc.PreProcessHandler externalPreProcessingHandler;
+ private AustinHarris.JsonRpc.PostProcessHandler externalPostProcessingHandler;
private Func externalErrorHandler;
private Func parseErrorHandler;
- private Dictionary Handlers { get; set; }
#endregion
///
@@ -151,27 +151,41 @@ private void RemoveRpcException()
#region Public Methods
///
- /// Registers a jsonRpc method name (key) to be mapped to a specific function
+ /// Allows you to register all the functions on a Pojo Type that have been attributed as [JsonRpcMethod] to the specified sessionId
///
- /// The Method as it will be called from JsonRpc
- /// The method that will be invoked
- ///
- public bool Register(string key, Delegate handle)
+ /// The session to register against
+ /// The instance containing JsonRpcMethods to register
+ public static void RegisterInstance(string sessionID, object instance)
{
- var result = false;
+ ServiceBinder.BindService(sessionID, instance);
+ }
- if (!this.Handlers.ContainsKey(key))
- {
- this.Handlers.Add(key, handle);
- }
+ ///
+ /// Allows you to register any function, lambda, etc even when not attributed with JsonRpcMethod.
+ /// Requires you to specify all types and defaults
+ ///
+ /// The method name that will map to the registered function
+ /// The parameter names and types that will be positionally bound to the function
+ /// Optional default values for parameters
+ /// A reference to the Function
+ public void RegisterFuction(string methodName, Dictionary parameterNameTypeMapping, Dictionary parameterNameDefaultValueMapping, Delegate implementation)
+ {
+ MetaData.AddService(methodName, parameterNameTypeMapping, parameterNameDefaultValueMapping, implementation);
+ }
- return result;
+ public void UnRegisterFunction(string methodName)
+ {
+ MetaData.Services.Remove(methodName);
}
- public void UnRegister(string key)
+ public void SetPreProcessHandler(AustinHarris.JsonRpc.PreProcessHandler handler)
{
- this.Handlers.Remove(key);
- MetaData.Services.Remove(key);
+ externalPreProcessingHandler = handler;
+ }
+
+ public void SetPostProcessHandler(AustinHarris.JsonRpc.PostProcessHandler handler)
+ {
+ externalPostProcessingHandler = handler;
}
///
@@ -187,84 +201,92 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
var preProcessingException = PreProcess(Rpc, RpcContext);
if (preProcessingException != null)
{
- return new JsonResponse() { Error = preProcessingException,
- Id = Rpc.Id };
+ JsonResponse response = new JsonResponse()
+ {
+ Error = preProcessingException,
+ Id = Rpc.Id
+ };
+ //callback is called - if it is empty then nothing will be done
+ //return response always- if callback is empty or not
+ return PostProcess(Rpc, response, RpcContext);
}
SMDService metadata = null;
Delegate handle = null;
- var haveDelegate = this.Handlers.TryGetValue(Rpc.Method, out handle);
- var haveMetadata = this.MetaData.Services.TryGetValue(Rpc.Method, out metadata);
-
- if (haveDelegate == false || haveMetadata == false || metadata == null || handle == null)
+ if (this.MetaData.Services.TryGetValue(Rpc.Method, out metadata))
{
- return new JsonResponse() { Result = null, Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."), Id = Rpc.Id };
- }
- if (Rpc.Params is ICollection == false)
+ handle = metadata.dele;
+ } else if (metadata == null)
{
- return new JsonResponse()
+ JsonResponse response = new JsonResponse()
{
Result = null,
- Error = new JsonRpcException(-32602,
- "Invalid params", "The number of parameters could not be counted"),
+ Error = new JsonRpcException(-32601, "Method not found", "The method does not exist / is not available."),
Id = Rpc.Id
};
+ return PostProcess(Rpc, response, RpcContext);
}
- bool isJObject = Rpc.Params is Newtonsoft.Json.Linq.JObject;
- bool isJArray = Rpc.Params is Newtonsoft.Json.Linq.JArray;
object[] parameters = null;
bool expectsRefException = false;
var metaDataParamCount = metadata.parameters.Count(x => x != null);
+
+ var loopCt = 0;
var getCount = Rpc.Params as ICollection;
- var loopCt = getCount.Count;
+ if (getCount != null)
+ {
+ loopCt = getCount.Count;
+ }
+
var paramCount = loopCt;
- if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount-1].ObjectType.Name.Contains(typeof(JsonRpcException).Name))
+ if (paramCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount - 1].ObjectType.Name.Equals(Name_of_JSONRPCEXCEPTION))
{
paramCount++;
expectsRefException = true;
}
parameters = new object[paramCount];
- if (isJArray)
+ if (Rpc.Params is Newtonsoft.Json.Linq.JArray)
{
var jarr = ((Newtonsoft.Json.Linq.JArray)Rpc.Params);
- //var loopCt = jarr.Count;
- //var pCount = loopCt;
- //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException))
- // pCount++;
- //parameters = new object[pCount];
- for (int i = 0; i < loopCt; i++)
+ for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++)
{
parameters[i] = CleanUpParameter(jarr[i], metadata.parameters[i]);
- }
+ }
}
- else if (isJObject)
+ else if (Rpc.Params is Newtonsoft.Json.Linq.JObject)
{
- var jo = Rpc.Params as Newtonsoft.Json.Linq.JObject;
- //var loopCt = jo.Count;
- //var pCount = loopCt;
- //if (pCount == metaDataParamCount - 1 && metadata.parameters[metaDataParamCount].GetType() == typeof(JsonRpcException))
- // pCount++;
- //parameters = new object[pCount];
- var asDict = jo as IDictionary;
- for (int i = 0; i < loopCt; i++)
+ var asDict = Rpc.Params as IDictionary;
+ for (int i = 0; i < loopCt && i < metadata.parameters.Length; i++)
{
- if (asDict.ContainsKey(metadata.parameters[i].Name) == false)
+ if (asDict.ContainsKey(metadata.parameters[i].Name) == true)
{
- return new JsonResponse()
+ parameters[i] = CleanUpParameter(asDict[metadata.parameters[i].Name], metadata.parameters[i]);
+ continue;
+ }
+ else
+ {
+ var foundDefault = metadata.defaultValues
+ .FirstOrDefault(defaul => defaul.Name == metadata.parameters[i].Name);
+ if (foundDefault != null)
+ {
+ parameters[i] = foundDefault.Value;
+ continue;
+ }
+
+ JsonResponse response = new JsonResponse()
{
Error = ProcessException(Rpc,
new JsonRpcException(-32602,
"Invalid params",
string.Format("Named parameter '{0}' was not present.",
metadata.parameters[i].Name)
- ))
- ,Id = Rpc.Id
+ )),
+ Id = Rpc.Id
};
+ return PostProcess(Rpc, response, RpcContext);
}
- parameters[i] = CleanUpParameter(jo[metadata.parameters[i].Name], metadata.parameters[i]);
}
}
@@ -273,25 +295,37 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
// if the rpc-call didn't supply a value for an optional parameter, we should be assinging the default value of it.
if (parameters.Length < metaDataParamCount && metadata.defaultValues.Length > 0) // rpc call didn't set values for all optional parameters, so we need to assign the default values for them.
{
- var paramIndex = parameters.Length; // the index we should start storing default values of optional parameters.
+ var suppliedParamsCount = parameters.Length; // the index we should start storing default values of optional parameters.
var missingParamsCount = metaDataParamCount - parameters.Length; // the amount of optional parameters without a value set by rpc-call.
- Array.Resize(ref parameters, parameters.Length + metadata.defaultValues.Length); // resize the array to include all optional parameters.
+ Array.Resize(ref parameters, parameters.Length + missingParamsCount); // resize the array to include all optional parameters.
- // we need to add in reverse order as parameters can appear after all required parameters.
- // as some of the optional parameters could already have assigned their values in rpc-call,
- // by starting from the end we can make sure we only add the required default values.
- for (int k = missingParamsCount; k > 0; k--)
+ for (int paramIndex = parameters.Length - 1, defaultIndex = metadata.defaultValues.Length - 1; // fill missing parameters from the back
+ paramIndex >= suppliedParamsCount && defaultIndex >= 0; // to don't overwrite supplied ones.
+ paramIndex--, defaultIndex--)
{
- var optionalParamIndex = k - 1; // the index of the optional parameter we will be currently setting a default value.
- parameters[paramIndex] = metadata.defaultValues[optionalParamIndex].Value; // set the default value for the optional parameter that rpc-call didn't set a value for.
- paramIndex++;
- paramCount++; // we need to increase the paramCount by one each time we add default-value for an optional parameter that rpc-call didn't set a value for.
+ parameters[paramIndex] = metadata.defaultValues[defaultIndex].Value;
+ }
+
+ if (missingParamsCount > metadata.defaultValues.Length)
+ {
+ JsonResponse response = new JsonResponse
+ {
+ Error = ProcessException(Rpc,
+ new JsonRpcException(-32602,
+ "Invalid params",
+ string.Format(
+ "Number of default parameters {0} not sufficient to fill all missing parameters {1}",
+ metadata.defaultValues.Length, missingParamsCount)
+ )),
+ Id = Rpc.Id
+ };
+ return PostProcess(Rpc, response, RpcContext);
}
}
-
+
if (parameters.Length != metaDataParamCount)
{
- return new JsonResponse()
+ JsonResponse response = new JsonResponse()
{
Error = ProcessException(Rpc,
new JsonRpcException(-32602,
@@ -302,76 +336,84 @@ public JsonResponse Handle(JsonRequest Rpc, Object RpcContext = null)
)),
Id = Rpc.Id
};
+ return PostProcess(Rpc, response, RpcContext);
}
try
{
var results = handle.DynamicInvoke(parameters);
- var last = parameters.Length>0 ? parameters[paramCount - 1]:null;
- JsonRpcException contextException;
- if (Task.CurrentId.HasValue && RpcExceptions.TryRemove(Task.CurrentId.Value, out contextException))
+
+ var last = parameters.LastOrDefault();
+ var contextException = RpcGetAndRemoveRpcException();
+ JsonResponse response = null;
+ if (contextException != null)
{
- return new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id };
+ response = new JsonResponse() { Error = ProcessException(Rpc, contextException), Id = Rpc.Id };
}
- if (expectsRefException && last != null && last is JsonRpcException)
+ else if (expectsRefException && last != null && last is JsonRpcException)
{
- return new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id };
+ response = new JsonResponse() { Error = ProcessException(Rpc, last as JsonRpcException), Id = Rpc.Id };
}
-
- return new JsonResponse() { Result = results };
+ else
+ {
+ response = new JsonResponse() { Result = results };
+ }
+ return PostProcess(Rpc, response, RpcContext);
}
catch (Exception ex)
{
+ JsonResponse response;
if (ex is TargetParameterCountException)
{
- return new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) };
+ response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32602, "Invalid params", ex)) };
+ return PostProcess(Rpc, response, RpcContext);
}
// We really dont care about the TargetInvocationException, just pass on the inner exception
if (ex is JsonRpcException)
{
- return new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) };
+ response = new JsonResponse() { Error = ProcessException(Rpc, ex as JsonRpcException) };
+ return PostProcess(Rpc, response, RpcContext);
}
if (ex.InnerException != null && ex.InnerException is JsonRpcException)
{
- return new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) };
+ response = new JsonResponse() { Error = ProcessException(Rpc, ex.InnerException as JsonRpcException) };
+ return PostProcess(Rpc, response, RpcContext);
}
else if (ex.InnerException != null)
{
- return new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) };
+ response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex.InnerException)) };
+ return PostProcess(Rpc, response, RpcContext);
}
- return new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) };
+ response = new JsonResponse() { Error = ProcessException(Rpc, new JsonRpcException(-32603, "Internal Error", ex)) };
+ return PostProcess(Rpc, response, RpcContext);
}
finally
{
RemoveRpcContext();
}
}
+ #endregion
+ [ThreadStatic]
+ static object __currentRpcContext;
private void AddRpcContext(object RpcContext)
{
- if (Task.CurrentId != null)
- RpcContexts[Task.CurrentId.Value] = RpcContext;
+ __currentRpcContext = RpcContext;
}
private void RemoveRpcContext()
{
- if (Task.CurrentId != null)
- {
- var id = Task.CurrentId.Value;
- RpcContexts[id] = null;
- object va;
- RpcContexts.TryRemove(id, out va);
- }
+ __currentRpcContext = null;
}
-
- private JsonRpcException ProcessException(JsonRequest req,JsonRpcException ex)
+
+ private JsonRpcException ProcessException(JsonRequest req, JsonRpcException ex)
{
- if(externalErrorHandler!=null)
- return externalErrorHandler(req,ex);
+ if (externalErrorHandler != null)
+ return externalErrorHandler(req, ex);
return ex;
}
- internal JsonRpcException ProcessParseException(string req,JsonRpcException ex)
+ internal JsonRpcException ProcessParseException(string req, JsonRpcException ex)
{
if (parseErrorHandler != null)
return parseErrorHandler(req, ex);
@@ -385,42 +427,95 @@ internal void SetParseErrorHandler(Func
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "jsonrpc")]
- public string JsonRpc { get { return "2.0"; } }
+ public string JsonRpc { get; set; } = "2.0";
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "result")]
public T Result { get; set; }
diff --git a/Json-Rpc/JsonRpcProcessor.cs b/Json-Rpc/JsonRpcProcessor.cs
index 16a24b9..5020e88 100644
--- a/Json-Rpc/JsonRpcProcessor.cs
+++ b/Json-Rpc/JsonRpcProcessor.cs
@@ -5,401 +5,176 @@
using System.Reflection;
using System.IO;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
+using Newtonsoft.Json;
namespace AustinHarris.JsonRpc
{
public static class JsonRpcProcessor
{
- public static void Process(JsonRpcStateAsync async, object context = null)
+ public static void Process(JsonRpcStateAsync async, object context = null,
+ JsonSerializerSettings settings = null)
{
- var t = Task.Factory.StartNew((_async) =>
- {
- var i = (Tuple)_async;
- ProcessJsonRpcState(i.Item1,i.Item2);
- }, new Tuple(async,context));
-
+ Process(Handler.DefaultSessionId(), async, context, settings);
}
- public static void Process(string sessionId, JsonRpcStateAsync async, object context = null)
+ public static void Process(string sessionId, JsonRpcStateAsync async, object context = null,
+ JsonSerializerSettings settings = null)
{
- var t = Task.Factory.StartNew((_async) =>
- {
- var i = (Tuple)_async;
- ProcessJsonRpcState(i.Item1, i.Item2, i.Item3);
- }, new Tuple(sessionId, async, context));
-
+ Process(sessionId, async.JsonRpc, context, settings)
+ .ContinueWith(t =>
+ {
+ async.Result = t.Result;
+ async.SetCompleted();
+ });
}
- internal static void ProcessJsonRpcState(JsonRpcStateAsync async, object jsonRpcContext = null)
+
+ public static Task Process(string jsonRpc, object context = null,
+ JsonSerializerSettings settings = null)
{
- ProcessJsonRpcState(Handler.DefaultSessionId(), async, jsonRpcContext);
+ return Process(Handler.DefaultSessionId(), jsonRpc, context, settings);
}
- internal static void ProcessJsonRpcState(string sessionId, JsonRpcStateAsync async, object jsonRpcContext = null)
- {
- var context = async.AsyncState;
- JsonRequest[] rpcBatch = null;
- JsonResponse[] responseBatch = null;
+ public static Task Process(string sessionId, string jsonRpc, object context = null,
+ JsonSerializerSettings settings = null)
+ {
+ return Task.Factory.StartNew((_) =>
+ {
+ var tuple = (Tuple)_;
+ return ProcessSync(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4);
+ }, new Tuple(sessionId, jsonRpc, context, settings));
+ }
- JsonRequest rpc = null;
+ public static string ProcessSync(string sessionId, string jsonRpc, object jsonRpcContext,
+ JsonSerializerSettings settings = null)
+ {
var handler = Handler.GetSessionHandler(sessionId);
- var callback = string.Empty;
-
- var response = new JsonResponse();
- response.Result = null;
- response.Error = null;
- string json = async.JsonRpc;
-
- if (isSingleRpc(json))
+ JsonRequest[] batch = null;
+ try
+ {
+ if (isSingleRpc(jsonRpc))
{
- try
- {
- if (json.Length > 0)
- {
- rpc = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
- if (rpc == null)
- {
- response.Result = null;
- response.Id = null;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text."));
- }
- else
- {
- response.Id = rpc.Id;
- if (rpc.Method == null)
- {
- response.Result = null;
- response.Id = rpc.Id;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'"));
- }
- }
- }
- else
- {
- response.Result = null;
- response.Id = null;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "The JSON sent is not a valid Request object."));
- }
- }
- catch (Exception ex)
- {
- response.Result = null;
- if (rpc != null) response.Id = rpc.Id;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex));
- var result = Newtonsoft.Json.JsonConvert.SerializeObject(response);
- async.Result = result;
- async.SetCompleted();
- return;
- }
-
- if (response.Error == null
- && rpc != null
- && rpc.Method != null)
- {
- var data = Handler.GetSessionHandler(sessionId).Handle(rpc, jsonRpcContext);
- if (data != null)
- {
- response.Error = data.Error;
- response.Result = data.Result;
- var result = "";
- if (response.Id != null)// dont return a result for notifications
- {
- result=Newtonsoft.Json.JsonConvert.SerializeObject(response);
- }
- async.Result = result;
- async.SetCompleted();
- return;
- }
- }
-
- var err = Newtonsoft.Json.JsonConvert.SerializeObject(response);
-
- async.Result = err;
- async.SetCompleted();
+ var foo = JsonConvert.DeserializeObject(jsonRpc, settings);
+ batch = new[] { foo };
}
- else // this is a batch of requests
+ else
{
- try
- {
- rpcBatch = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
- responseBatch = new JsonResponse[rpcBatch.Length];
-
- for (int i = 0; i < rpcBatch.Length; i++)
- {
- responseBatch[i] = new JsonResponse();
- if (rpcBatch[i] == null)
- {
- responseBatch[i].Result = null;
- responseBatch[i].Id = null;
- responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text."));
- }
- else
- {
- responseBatch[i].Id = rpcBatch[i].Id;
- if (rpcBatch[i].Method == null)
- {
- responseBatch[i].Result = null;
- responseBatch[i].Error =handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'"));
- }
- }
- }
- }
- catch (Exception ex)
- {
- response.Result = null;
- if (rpc != null) response.Id = rpc.Id;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex));
- var result = Newtonsoft.Json.JsonConvert.SerializeObject(response);
- async.Result = result;
- async.SetCompleted();
- return;
- }
-
- // we should have a batch of RPC at this point
- var respBuilder = new StringBuilder();
- for (int i = 0; i < rpcBatch.Length; i++)
- {
- if (i == 0)
- {
- respBuilder.Append("[");
- }
-
- if (rpcBatch[i] == null || rpcBatch[i].Method == null)
- {
- responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'"));
- }
- else if (responseBatch[i].Error == null)
- {
- var data = handler.Handle(rpcBatch[i], jsonRpcContext);
- if (data != null)
- {
- responseBatch[i].Error = data.Error;
- responseBatch[i].Result = data.Result;
-
- }
- }
- // dont return a response for notifications.
- if (responseBatch[i].Id != null || responseBatch[i].Error != null)
- {
- var result = Newtonsoft.Json.JsonConvert.SerializeObject(responseBatch[i]);
- respBuilder.Append(result);
- if (i != rpcBatch.Length - 1)
- {
- respBuilder.Append(',');
- }
- }
-
- if (i == rpcBatch.Length - 1)
- {
- respBuilder.Append("]");
- var str = respBuilder.ToString();
- async.Result = str;
- async.SetCompleted(); // let IIS think we are completed now.
- return;
- }
- }
-
- // if we made it this far, then there were no items in the array
- response.Id = null;
- response.Result = null;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty."));
-
- var err = Newtonsoft.Json.JsonConvert.SerializeObject(response);
-
- async.Result = err;
- async.SetCompleted();
- }
- }
-
- public static Task Process(string jsonRpc, object context = null)
- {
- return Process(Handler.DefaultSessionId(), jsonRpc, context);
- }
- public static Task Process(string sessionId, string jsonRpc, object context = null)
- {
- var task = Task.Factory.StartNew((_) =>
+ batch = JsonConvert.DeserializeObject(jsonRpc, settings);
+ }
+ }
+ catch (Exception ex)
{
- // use invariant culture - we have to set it explicitly for every thread we create to
- // prevent any floating-point problems (mostly because of number formats in non en-US cultures).
- Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
-
- var tup = (Tuple)_;
- string _sessionId;
- string _jsonRpc;
- object _jsonRpcContext = null;
- _sessionId = tup.Item1;
- _jsonRpc = tup.Item2;
- _jsonRpcContext = tup.Item3;
- var handler = Handler.GetSessionHandler(_sessionId);
-
+ return Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse
+ {
+ Error = handler.ProcessParseException(jsonRpc, new JsonRpcException(-32700, "Parse error", ex))
+ }, settings);
+ }
- JsonRequest[] rpcBatch = null;
- JsonResponse[] responseBatch = null;
+ if (batch.Length == 0)
+ {
+ return Newtonsoft.Json.JsonConvert.SerializeObject(new JsonResponse
+ {
+ Error = handler.ProcessParseException(jsonRpc,
+ new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty."))
+ }, settings);
+ }
- JsonRequest rpc = null;
+ var singleBatch = batch.Length == 1;
+ StringBuilder sbResult = null;
+ for (var i = 0; i < batch.Length; i++)
+ {
+ var jsonRequest = batch[i];
+ var jsonResponse = new JsonResponse();
- var callback = string.Empty;
+ if (jsonRequest == null)
+ {
+ jsonResponse.Error = handler.ProcessParseException(jsonRpc,
+ new JsonRpcException(-32700, "Parse error",
+ "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text."));
+ }
+ else if (jsonRequest.Method == null)
+ {
+ jsonResponse.Error = handler.ProcessParseException(jsonRpc,
+ new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'"));
+ }
+ else if (!isSimpleValueType(jsonRequest.Id))
+ {
+ jsonResponse.Error = handler.ProcessParseException(jsonRpc,
+ new JsonRpcException(-32600, "Invalid Request", "Id property must be either null or string or integer."));
+ }
+ else
+ {
+ jsonResponse.Id = jsonRequest.Id;
- var response = new JsonResponse();
+ var data = handler.Handle(jsonRequest, jsonRpcContext);
- response.Result = null;
- response.Error = null;
+ if (data == null) continue;
- string json = _jsonRpc;
+ jsonResponse.JsonRpc = data.JsonRpc;
+ jsonResponse.Error = data.Error;
+ jsonResponse.Result = data.Result;
- if (isSingleRpc(json))
+ }
+ if (jsonResponse.Result == null && jsonResponse.Error == null)
{
- try
+ // Per json rpc 2.0 spec
+ // result : This member is REQUIRED on success.
+ // This member MUST NOT exist if there was an error invoking the method.
+ // Either the result member or error member MUST be included, but both members MUST NOT be included.
+ jsonResponse.Result = new Newtonsoft.Json.Linq.JValue((Object)null);
+ }
+ // special case optimization for single Item batch
+ if (singleBatch && (jsonResponse.Id != null || jsonResponse.Error != null))
+ {
+ StringWriter sw = new StringWriter();
+ JsonTextWriter writer = new JsonTextWriter(sw);
+ writer.WriteStartObject();
+ if (!string.IsNullOrEmpty(jsonResponse.JsonRpc))
{
- if (json.Length > 0)
- {
- rpc = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
- if (rpc == null)
- {
- response.Result = null;
- response.Id = null;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text."));
- }
- else
- {
- response.Id = rpc.Id;
- if (rpc.Method == null)
- {
- response.Result = null;
- response.Id = rpc.Id;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'"));
- }
- }
- }
- else
- {
- response.Result = null;
- response.Id = null;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "The JSON sent is not a valid Request object."));
- }
+ writer.WritePropertyName("jsonrpc"); writer.WriteValue(jsonResponse.JsonRpc);
}
- catch (Exception ex)
+ if (jsonResponse.Error != null)
{
- response.Result = null;
- if (rpc != null) response.Id = rpc.Id;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex));
- var result = Newtonsoft.Json.JsonConvert.SerializeObject(response);
- return result;
+ writer.WritePropertyName("error"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Error, settings));
}
-
- if (response.Error == null
- && rpc != null
- && rpc.Method != null)
+ else
{
- var data = handler.Handle(rpc, _jsonRpcContext);
- if (data != null)
- {
- response.Error = data.Error;
- response.Result = data.Result;
- var result = "";
- if (response.Id != null)// dont return a result for notifications
- {
- result = Newtonsoft.Json.JsonConvert.SerializeObject(response);
- }
- return result;
- }
+ writer.WritePropertyName("result"); writer.WriteRawValue(JsonConvert.SerializeObject(jsonResponse.Result, settings));
}
+ writer.WritePropertyName("id"); writer.WriteValue(jsonResponse.Id);
+ writer.WriteEndObject();
+ return sw.ToString();
- var err = Newtonsoft.Json.JsonConvert.SerializeObject(response);
-
- return err;
+ //return JsonConvert.SerializeObject(jsonResponse);
+ }
+ else if (jsonResponse.Id == null && jsonResponse.Error == null)
+ {
+ // do nothing
+ sbResult = new StringBuilder(0);
}
- else // this is a batch of requests
+ else
{
- try
+ // write out the response
+ if (i == 0)
{
- rpcBatch = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
- responseBatch = new JsonResponse[rpcBatch.Length];
-
- for (int i = 0; i < rpcBatch.Length; i++)
- {
- responseBatch[i] = new JsonResponse();
- if (rpcBatch[i] == null)
- {
- responseBatch[i].Result = null;
- responseBatch[i].Id = null;
- responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", "Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text."));
- }
- else
- {
- responseBatch[i].Id = rpcBatch[i].Id;
- if (rpcBatch[i].Method == null)
- {
- responseBatch[i].Result = null;
- responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'"));
- }
- }
- }
+ sbResult = new StringBuilder("[");
}
- catch (Exception ex)
+
+ sbResult.Append(JsonConvert.SerializeObject(jsonResponse, settings));
+ if (i < batch.Length - 1)
{
- response.Result = null;
- if (rpc != null) response.Id = rpc.Id;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(-32700, "Parse error", ex));
- var result = Newtonsoft.Json.JsonConvert.SerializeObject(response);
- return result;
+ sbResult.Append(',');
}
-
- // we should have a batch of RPC at this point
- var respBuilder = new StringBuilder();
- for (int i = 0; i < rpcBatch.Length; i++)
+ else if (i == batch.Length - 1)
{
- if (i == 0)
- {
- respBuilder.Append("[");
- }
-
- if (rpcBatch[i] == null || rpcBatch[i].Method == null)
- {
- responseBatch[i].Error = handler.ProcessParseException(json, new JsonRpcException(-32600, "Invalid Request", "Missing property 'method'"));
- }
- else if (responseBatch[i].Error == null)
- {
- var data = Handler.GetSessionHandler(_sessionId).Handle(rpcBatch[i], _jsonRpcContext);
- if (data != null)
- {
- responseBatch[i].Error = data.Error;
- responseBatch[i].Result = data.Result;
-
- }
- }
- // dont return a response for notifications.
- if (responseBatch[i].Id != null || responseBatch[i].Error != null)
- {
- var result = Newtonsoft.Json.JsonConvert.SerializeObject(responseBatch[i]);
- respBuilder.Append(result);
- if (i != rpcBatch.Length - 1)
- {
- respBuilder.Append(',');
- }
- }
-
- if (i == rpcBatch.Length - 1)
- {
- respBuilder.Append("]");
- var str = respBuilder.ToString();
- return str;
- }
+ sbResult.Append(']');
}
-
- // if we made it this far, then there were no items in the array
- response.Id = null;
- response.Result = null;
- response.Error = handler.ProcessParseException(json, new JsonRpcException(3200, "Invalid Request", "Batch of calls was empty."));
-
- var err = Newtonsoft.Json.JsonConvert.SerializeObject(response);
-
- return err;
}
- }, new Tuple(sessionId, jsonRpc, context));
- return task;
+ }
+ return sbResult.ToString();
}
private static bool isSingleRpc(string json)
@@ -411,5 +186,15 @@ private static bool isSingleRpc(string json)
}
return true;
}
+
+ private static bool isSimpleValueType(object property)
+ {
+ if (property == null)
+ return true;
+ return property.GetType() == typeof(System.String) ||
+ property.GetType() == typeof(System.Int64) ||
+ property.GetType() == typeof(System.Int32) ||
+ property.GetType() == typeof(System.Int16);
+ }
}
}
diff --git a/Json-Rpc/JsonRpcService.cs b/Json-Rpc/JsonRpcService.cs
index c5a3569..d8ec961 100644
--- a/Json-Rpc/JsonRpcService.cs
+++ b/Json-Rpc/JsonRpcService.cs
@@ -1,65 +1,22 @@
namespace AustinHarris.JsonRpc
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using AustinHarris.JsonRpc;
-
+ ///
+ /// For routing use SessionId
+ ///
public abstract class JsonRpcService
{
protected JsonRpcService()
{
- buildService(Handler.DefaultSessionId());
+ ServiceBinder.BindService(Handler.DefaultSessionId(), this);
}
+ ///
+ /// Routing by SessionId
+ ///
+ ///
protected JsonRpcService(string sessionID)
{
- buildService(sessionID);
- }
-
- private void buildService(string sessionID)
- {
- // get the registerMethod.
- // Method that matches Func
- var regMethod = typeof(Handler).GetMethod("Register");
-
- // var assem = Assembly.GetExecutingAssembly();
- // var TypesWithHandlers = assem.GetTypes().Where(f => f.GetCustomAttributes(typeof(JsonRpcAttribute), false).Length > 0);
- var item = this.GetType();
-
- var methods = item.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(m => m.GetCustomAttributes(typeof(JsonRpcMethodAttribute), false).Length > 0);
- foreach (var meth in methods)
- {
- Dictionary paras = new Dictionary();
- Dictionary defaultValues = new Dictionary(); // dictionary that holds default values for optional params.
-
- var paramzs = meth.GetParameters();
-
- List parameterTypeArray = new List();
- for (int i = 0; i < paramzs.Length; i++)
- {
- // reflection attribute information for optional parameters
- //http://stackoverflow.com/questions/2421994/invoking-methods-with-optional-parameters-through-reflection
- paras.Add(paramzs[i].Name, paramzs[i].ParameterType);
-
- if (paramzs[i].IsOptional) // if the parameter is an optional, add the default value to our default values dictionary.
- defaultValues.Add(paramzs[i].Name, paramzs[i].DefaultValue);
- }
-
- var resType = meth.ReturnType;
- paras.Add("returns", resType); // add the return type to the generic parameters list.
-
- var atdata = meth.GetCustomAttributes(typeof(JsonRpcMethodAttribute), false);
- foreach (JsonRpcMethodAttribute handlerAttribute in atdata)
- {
- var methodName = handlerAttribute.JsonMethodName == string.Empty ? meth.Name : handlerAttribute.JsonMethodName;
- var newDel = Delegate.CreateDelegate(System.Linq.Expressions.Expression.GetDelegateType(paras.Values.ToArray()), this /*Need to add support for other methods outside of this instance*/, meth);
- var handlerSession = Handler.GetSessionHandler(sessionID);
- regMethod.Invoke(handlerSession, new object[] { methodName, newDel });
- handlerSession.MetaData.AddService(methodName, paras, defaultValues);
- }
- }
+ ServiceBinder.BindService(sessionID, this);
}
}
-}
+}
\ No newline at end of file
diff --git a/Json-Rpc/Properties/AssemblyInfo.cs b/Json-Rpc/Properties/AssemblyInfo.cs
deleted file mode 100644
index 802d0fd..0000000
--- a/Json-Rpc/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Json-Rpc.Net Core")]
-[assembly: AssemblyDescription("Core functionality for JsonRpc.Net")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Austin Harris")]
-[assembly: AssemblyProduct("Json-Rpc.Net Core")]
-[assembly: AssemblyCopyright("Austin Harris")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("2f8036b2-223d-4b90-b6a9-fadddeb3ac0d")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-[assembly: AssemblyVersion("1.0.5.0")]
-[assembly: AssemblyFileVersion("1.0.5.0")]
diff --git a/Json-Rpc/SMDService.cs b/Json-Rpc/SMDService.cs
index 0487a36..fe84bb5 100644
--- a/Json-Rpc/SMDService.cs
+++ b/Json-Rpc/SMDService.cs
@@ -34,31 +34,37 @@ public SMD ()
TypeHashes = new List();
}
- public void AddService(string method, Dictionary parameters, Dictionary defaultValues)
+ internal void AddService(string method, Dictionary parameters, Dictionary defaultValues, Delegate dele)
{
- var newService = new SMDService(transport,"JSON-RPC-2.0",parameters, defaultValues);
+ var newService = new SMDService(transport,"JSON-RPC-2.0",parameters, defaultValues, dele);
Services.Add(method,newService);
}
public static int AddType(JObject jo)
{
- var hash = "t_" + jo.ToString().GetHashCode();
+ var hash = string.Format("t_{0}", jo.ToString().GetHashCode());
+
lock (TypeHashes)
- {
- var idx = 0;
- if (TypeHashes.Contains(hash) == false)
- {
- TypeHashes.Add(hash);
- idx = TypeHashes.IndexOf(hash);
- Types.Add(idx, jo);
- }
+ {
+ if (TypeHashes.Contains(hash)) return TypeHashes.IndexOf(hash);
+
+ TypeHashes.Add(hash);
+ var idx = TypeHashes.IndexOf(hash);
+ Types.Add(idx, jo);
}
+
return TypeHashes.IndexOf(hash);
}
+
+ public static bool ContainsType(JObject jo)
+ {
+ return TypeHashes.Contains(string.Format("t_{0}", jo.ToString().GetHashCode()));
+ }
}
public class SMDService
{
+ public Delegate dele;
///
/// Defines a service method http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html
///
@@ -66,9 +72,10 @@ public class SMDService
/// URL, PATH, JSON, JSON-RPC-1.0, JSON-RPC-1.1, JSON-RPC-2.0
///
///
- public SMDService(string transport, string envelope, Dictionary parameters, Dictionary defaultValues )
+ public SMDService(string transport, string envelope, Dictionary parameters, Dictionary defaultValues, Delegate dele)
{
// TODO: Complete member initialization
+ this.dele = dele;
this.transport = transport;
this.envelope = envelope;
this.parameters = new SMDAdditionalParameters[parameters.Count-1]; // last param is return type similar to Func<,>
@@ -163,11 +170,14 @@ internal static int GetTypeRecursive(Type t)
{
JObject jo = new JObject();
jo.Add("__name", t.Name.ToLower());
- if (isSimpleType(t))
+
+ if (isSimpleType(t) || SMD.ContainsType(jo))
{
return SMD.AddType(jo);
}
+ var retVal = SMD.AddType(jo);
+
var genArgs = t.GetGenericArguments();
PropertyInfo[] properties = t.GetProperties();
FieldInfo[] fields = t.GetFields();
@@ -225,7 +235,7 @@ internal static int GetTypeRecursive(Type t)
}
}
- return SMD.AddType(jo);
+ return retVal;
}
internal static bool isSimpleType(Type t)
diff --git a/Json-Rpc/ServiceBinder.cs b/Json-Rpc/ServiceBinder.cs
new file mode 100644
index 0000000..20423a6
--- /dev/null
+++ b/Json-Rpc/ServiceBinder.cs
@@ -0,0 +1,71 @@
+namespace AustinHarris.JsonRpc
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using AustinHarris.JsonRpc;
+
+ public static class ServiceBinder
+ {
+ public static void BindService() where T : new()
+ {
+ BindService(Handler.DefaultSessionId());
+ }
+ public static void BindService(string sessionID) where T : new()
+ {
+ BindService(sessionID, new T());
+ }
+
+ public static void BindService(string sessionID, Object instance)
+ {
+ var item = instance.GetType(); // var item = typeof(T);
+
+ var methods = item.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(m => m.GetCustomAttributes(typeof(JsonRpcMethodAttribute), false).Length > 0);
+ foreach (var meth in methods)
+ {
+ Dictionary paras = new Dictionary();
+ Dictionary defaultValues = new Dictionary(); // dictionary that holds default values for optional params.
+
+ var paramzs = meth.GetParameters();
+
+ List parameterTypeArray = new List();
+ for (int i = 0; i < paramzs.Length; i++)
+ {
+ string paramName;
+ var paramAttrs = paramzs[i].GetCustomAttributes(typeof(JsonRpcParamAttribute), false);
+ if (paramAttrs.Length > 0)
+ {
+ paramName = ((JsonRpcParamAttribute)paramAttrs[0]).JsonParamName;
+ if (string.IsNullOrEmpty(paramName))
+ {
+ paramName = paramzs[i].Name;
+ }
+ }
+ else
+ {
+ paramName = paramzs[i].Name;
+ }
+ // reflection attribute information for optional parameters
+ //http://stackoverflow.com/questions/2421994/invoking-methods-with-optional-parameters-through-reflection
+ paras.Add(paramName, paramzs[i].ParameterType);
+
+ if (paramzs[i].IsOptional) // if the parameter is an optional, add the default value to our default values dictionary.
+ defaultValues.Add(paramName, paramzs[i].DefaultValue);
+ }
+
+ var resType = meth.ReturnType;
+ paras.Add("returns", resType); // add the return type to the generic parameters list.
+
+ var atdata = meth.GetCustomAttributes(typeof(JsonRpcMethodAttribute), false);
+ foreach (JsonRpcMethodAttribute handlerAttribute in atdata)
+ {
+ var methodName = handlerAttribute.JsonMethodName == string.Empty ? meth.Name : handlerAttribute.JsonMethodName;
+ var newDel = Delegate.CreateDelegate(System.Linq.Expressions.Expression.GetDelegateType(paras.Values.ToArray()), instance /*Need to add support for other methods outside of this instance*/, meth);
+ var handlerSession = Handler.GetSessionHandler(sessionID);
+ handlerSession.MetaData.AddService(methodName, paras, defaultValues, newDel);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Json-Rpc/packages.config b/Json-Rpc/packages.config
deleted file mode 100644
index 12fef57..0000000
--- a/Json-Rpc/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 629457b..7847e23 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,37 @@
+

json-rpc.net
============
+ 
JSON-RPC.Net is a high performance Json-Rpc 2.0 server, leveraging the popular JSON.NET library. Host in ASP.NET, also supports sockets and pipes, oh my!
+## Performance
+
+These are results from running the TestServer_Console project.
+
+##### Xeon E-2176M @ 2.70GHz 64.0 GB (Date: Thu Apr 30 17:34:22 2020 -0600)
+
+```
+Starting benchmark
+processed 50 rpc in 137ms for 364.96 rpc/sec
+processed 100 rpc in 0ms for ∞ rpc/sec
+processed 300 rpc in 1ms for 300,000.00 rpc/sec
+processed 1,200 rpc in 7ms for 171,428.57 rpc/sec
+processed 6,000 rpc in 26ms for 230,769.23 rpc/sec
+processed 36,000 rpc in 166ms for 216,867.47 rpc/sec
+processed 252,000 rpc in 1,121ms for 224,799.29 rpc/sec
+Finished benchmark...
+```
+
+## Do you like this?
+
+[](https://www.buymeacoffee.com/Ekati)
+
+
##### Requirements
-* dotnet 4.0 or mono
+* dotnet-standard (dotnet core | mono | .net framework)
##### License
JSON-RPC.net is licensed under The MIT License (MIT), check the [LICENSE](https://github.com/CoiniumServ/JSON-RPC.NET/blob/master/LICENSE) file for details.
@@ -24,12 +49,13 @@ PM> Install-Package AustinHarris.JsonRpc
To install JSON-RPC.NET AspNet, run the following command in the Package Manager Console
```
-PM> Install-Package AustinHarris.AspNet
+PM> Install-Package AustinHarris.JsonRpc.AspNet
```
-##### Performance
-Under ideal conditions > 120k rpc/sec (cpu i7-2600,console server, no IO bottleneck)
+
+
+
##### Getting Started & Documentation
diff --git a/TestServer_Console/Program.cs b/TestServer_Console/Program.cs
index 8460d12..df3152f 100644
--- a/TestServer_Console/Program.cs
+++ b/TestServer_Console/Program.cs
@@ -5,6 +5,7 @@
using AustinHarris.JsonRpc;
using System.Threading;
using System.Diagnostics;
+using System.Threading.Tasks;
namespace TestServer_Console
{
@@ -16,36 +17,29 @@ class Program
static void Main(string[] args)
{
- string input = "";
- do
+ PrintOptions();
+ for (string line = Console.ReadLine(); line != "q"; line = Console.ReadLine())
{
- input = PrintOptions();
- if (string.IsNullOrWhiteSpace(input))
+ if (string.IsNullOrWhiteSpace(line))
Benchmark();
- else if (input.StartsWith("C", StringComparison.CurrentCultureIgnoreCase))
+ else if (line.StartsWith("c", StringComparison.CurrentCultureIgnoreCase))
ConsoleInput();
- else
- PrintOptions();
- } while (input != "x");
+ PrintOptions();
+ }
}
- private static string PrintOptions()
+ private static void PrintOptions()
{
Console.WriteLine("Hit Enter to run benchmark");
Console.WriteLine("'c' to start reading console input");
- Console.WriteLine("'x' to exit");
- return Console.ReadLine();
+ Console.WriteLine("'q' to quit");
}
private static void ConsoleInput()
{
- var rpcResultHandler = new AsyncCallback(_ => Console.WriteLine(((JsonRpcStateAsync)_).Result));
-
for (string line = Console.ReadLine(); !string.IsNullOrEmpty(line); line = Console.ReadLine())
{
- var async = new JsonRpcStateAsync(rpcResultHandler, null);
- async.JsonRpc = line;
- JsonRpcProcessor.Process(async);
+ JsonRpcProcessor.Process(line).ContinueWith(response => Console.WriteLine( response.Result ));
}
}
@@ -60,25 +54,21 @@ private static void Benchmark()
{
cnt *= iteration;
ctr = 0;
+ Task[] tasks = new Task[cnt];
var sw = Stopwatch.StartNew();
- AutoResetEvent are = new AutoResetEvent(false);
- var rpcResultHandler = new AsyncCallback(_ =>
- {
- if(Interlocked.Increment(ref ctr) == cnt)
- {
- sw.Stop();
- Console.WriteLine("processed {0} rpc in {1}ms for {2} rpc/sec",cnt,sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds);
- are.Set();
- }
- });
- for (int i = 0; i < cnt; i++)
+ var sessionid = Handler.DefaultSessionId();
+ for (int i = 0; i < cnt; i+=5)
{
- var async = new JsonRpcStateAsync(rpcResultHandler, null);
- async.JsonRpc = "{'method':'add','params':[1,2],'id':1}";
- JsonRpcProcessor.Process(async);
+ tasks[i] = JsonRpcProcessor.Process(sessionid, "{'method':'add','params':[1,2],'id':1}");
+ tasks[i+1] = JsonRpcProcessor.Process(sessionid, "{'method':'addInt','params':[1,7],'id':2}");
+ tasks[i+2] = JsonRpcProcessor.Process(sessionid, "{'method':'NullableFloatToNullableFloat','params':[1.23],'id':3}");
+ tasks[i+3] = JsonRpcProcessor.Process(sessionid, "{'method':'Test2','params':[3.456],'id':4}");
+ tasks[i+4] = JsonRpcProcessor.Process(sessionid, "{'method':'StringMe','params':['Foo'],'id':5}");
}
- are.WaitOne();
+ Task.WaitAll(tasks);
+ sw.Stop();
+ Console.WriteLine("processed {0:N0} rpc in \t {1:N0}ms for \t {2:N} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds);
}
diff --git a/TestServer_Console/Properties/AssemblyInfo.cs b/TestServer_Console/Properties/AssemblyInfo.cs
deleted file mode 100644
index fdd1edf..0000000
--- a/TestServer_Console/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("TestServer_Console")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("TestServer_Console")]
-[assembly: AssemblyCopyright("Copyright © 2012")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("5e7696bc-52cc-48f8-a575-40b17165ee20")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TestServer_Console/TestServer_Console.csproj b/TestServer_Console/TestServer_Console.csproj
index 91ea00d..ba5f427 100644
--- a/TestServer_Console/TestServer_Console.csproj
+++ b/TestServer_Console/TestServer_Console.csproj
@@ -1,83 +1,24 @@
-
-
-
- Debug
- x86
- 8.0.30703
- 2.0
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}
- Exe
- Properties
- TestServer_Console
- TestServer_Console
- v4.0
- Client
- 512
- SAK
- SAK
- SAK
- SAK
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- x86
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
- AnyCPU
- bin\Debug\
-
-
- AnyCPU
- bin\Release\
-
-
-
- False
- ..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}
- AustinHarris.JsonRpc
-
-
-
-
-
-
-
+
+
+
+ Austin Harris
+ Exe
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestServer_Console/packages.config b/TestServer_Console/packages.config
deleted file mode 100644
index 7106c62..0000000
--- a/TestServer_Console/packages.config
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/TestServer_Console/service.cs b/TestServer_Console/service.cs
index c0a09aa..6fc2602 100644
--- a/TestServer_Console/service.cs
+++ b/TestServer_Console/service.cs
@@ -14,6 +14,12 @@ private double add(double l, double r)
return l + r;
}
+ [JsonRpcMethod]
+ private int addInt(int l, int r)
+ {
+ return l + r;
+ }
+
[JsonRpcMethod]
public float? NullableFloatToNullableFloat(float? a)
{
@@ -25,5 +31,101 @@ private double add(double l, double r)
{
return x;
}
+
+ [JsonRpcMethod]
+ public string StringMe(string x)
+ {
+ return x;
+ }
+
+ [JsonRpcMethod]
+ private double add_1(double l, double r)
+ {
+ return l + r;
+ }
+
+ [JsonRpcMethod]
+ private int addInt_1(int l, int r)
+ {
+ return l + r;
+ }
+
+ [JsonRpcMethod]
+ public float? NullableFloatToNullableFloat_1(float? a)
+ {
+ return a;
+ }
+
+ [JsonRpcMethod]
+ public decimal? Test2_1(decimal x)
+ {
+ return x;
+ }
+
+ [JsonRpcMethod]
+ public string StringMe_1(string x)
+ {
+ return x;
+ }
+
+ [JsonRpcMethod]
+ private double add_2(double l, double r)
+ {
+ return l + r;
+ }
+
+ [JsonRpcMethod]
+ private int addInt_2(int l, int r)
+ {
+ return l + r;
+ }
+
+ [JsonRpcMethod]
+ public float? NullableFloatToNullableFloat_2(float? a)
+ {
+ return a;
+ }
+
+ [JsonRpcMethod]
+ public decimal? Test2_2(decimal x)
+ {
+ return x;
+ }
+
+ [JsonRpcMethod]
+ public string StringMe_2(string x)
+ {
+ return x;
+ }
+
+ [JsonRpcMethod]
+ private double add_3(double l, double r)
+ {
+ return l + r;
+ }
+
+ [JsonRpcMethod]
+ private int addInt_3(int l, int r)
+ {
+ return l + r;
+ }
+
+ [JsonRpcMethod]
+ public float? NullableFloatToNullableFloat_3(float? a)
+ {
+ return a;
+ }
+
+ [JsonRpcMethod]
+ public decimal? Test2_3(decimal x)
+ {
+ return x;
+ }
+
+ [JsonRpcMethod]
+ public string StringMe_3(string x)
+ {
+ return x;
+ }
}
}