diff --git a/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj b/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj
new file mode 100644
index 0000000..6d160cf
--- /dev/null
+++ b/AustinHarris.JsonRpc.Jsmn/AustinHarris.JsonRpc.Jsmn.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.0
+
+
+
+ true
+
+
+ true
+
+
+
diff --git a/AustinHarris.JsonRpc.Jsmn/Jsmn.cs b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs
new file mode 100644
index 0000000..01e2bea
--- /dev/null
+++ b/AustinHarris.JsonRpc.Jsmn/Jsmn.cs
@@ -0,0 +1,672 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace AustinHarris.JsonRpc.Jsmn
+{
+
+
+ /**
+ * JSON type identifier. Basic types are:
+ * o Object
+ * o Array
+ * o String
+ * o Other primitive: number, boolean (true/false) or null
+ */
+ public enum jsmntype_t
+ {
+ JSMN_UNDEFINED = 0,
+ JSMN_OBJECT = 1,
+ JSMN_ARRAY = 2,
+ JSMN_STRING = 3,
+ JSMN_PRIMITIVE = 4
+ }
+
+ public enum jsmnerr
+ {
+ /* Not enough tokens were provided */
+ JSMN_ERROR_NOMEM = -1,
+ /* Invalid character inside JSON string */
+ JSMN_ERROR_INVAL = -2,
+ /* The string is not a full JSON packet, more bytes expected */
+ JSMN_ERROR_PART = -3
+ }
+
+ /**
+ * JSON token description.
+ * type type (object, array, string etc.)
+ * start start position in JSON data string
+ * end end position in JSON data string
+ */
+ public struct jsmntok_t
+ {
+ public jsmntype_t type;
+ public int start;
+ public int end;
+ public int size;
+ public int parent;
+ };
+
+ /**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+ public struct jsmn_parser
+ {
+
+ public int pos; /* offset in the JSON string */
+ public int toknext; /* next token to allocate */
+ public int toksuper; /* superior token node, e.g parent object or array */
+ };
+
+
+ public static class jsmn
+ {
+ public static unsafe int parse(string json, jsmntok_t[] tokens)
+ {
+ fixed(jsmntok_t* thead = &tokens[0])
+ fixed (char* pjson = json)
+ {
+ jsmn_parser parser;
+ jsmn_c.init(&parser);
+ return jsmn_c.jsmn_parse(&parser, pjson, json.Length, thead, 100);
+
+ }
+ }
+
+ public static unsafe bool parseFirstField(string json, string fieldName, out string value)
+ {
+ const int count = 20;
+ jsmntok_t* tokens = stackalloc jsmntok_t[count];
+ var found = 0;
+ fixed (char* pjson = json)
+ {
+ jsmn_parser parser;
+ jsmn_c.init(&parser);
+ found = jsmn_c.jsmn_parse(&parser, pjson, json.Length, tokens, count);
+ }
+
+ for (int i = 0; i < found; i++)
+ {
+ var tokSz = tokens[i].end - tokens[i].start;
+ if (tokSz == fieldName.Length && String.Compare(fieldName, 0, json, tokens[i].start, tokSz) == 0)
+ {
+ i++;
+ value = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start);
+ return true;
+ }
+ }
+
+ value = string.Empty;
+ return false;
+
+ }
+
+ static readonly string idField = "id";
+ static readonly string paramsField = "params";
+ public static unsafe void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info)
+ {
+ const int count = 20;
+ jsmntok_t* tokens = stackalloc jsmntok_t[count];
+ var found = 0;
+ fixed (char* pjson = json)
+ {
+ jsmn_parser parser;
+ jsmn_c.init(&parser);
+ found = jsmn_c.jsmn_parse(&parser, pjson, json.Length, tokens, count);
+ }
+
+
+
+ for (int i = 0; i < found; i++)
+ {
+ var tokSz = tokens[i].end - tokens[i].start;
+ var current = tokens[i];
+ var currentval = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start);
+ if (tokSz == idField.Length && String.Compare(idField, 0, json, tokens[i].start, tokSz) == 0)
+ {
+ i++;
+ rawId = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start);
+ }
+
+ else if (tokSz == paramsField.Length && String.Compare(paramsField, 0, json, tokens[i].start, tokSz) == 0)
+ {
+ i++;
+ switch (tokens[i].type)
+ {
+ case jsmntype_t.JSMN_ARRAY:
+ var level = i;
+ i++;
+ while (tokens[i].parent == level)
+ {
+ switch (tokens[i].type)
+ {
+ case jsmntype_t.JSMN_UNDEFINED:
+ break;
+ case jsmntype_t.JSMN_OBJECT:
+ break;
+ case jsmntype_t.JSMN_ARRAY:
+ break;
+ case jsmntype_t.JSMN_STRING:
+ if (i - level == 1)
+ functionParameters.Item1 =
+ (T) Convert.ChangeType(
+ json.Substring(tokens[i].start, tokens[i].end - tokens[i].start),
+ typeof(T));
+ break;
+ case jsmntype_t.JSMN_PRIMITIVE:
+ if (i - level == 1)
+ if (info[0].Value.IsGenericType && info[0].Value.GenericTypeArguments.Length==1)
+ {
+ var substr = json.Substring(tokens[i].start,
+ tokens[i].end - tokens[i].start);
+ if(substr != "null"){
+ functionParameters.Item1 = (T)Convert.ChangeType(
+ substr,
+ info[0].Value.GenericTypeArguments[0]);
+ }
+ }
+ else {
+ functionParameters.Item1 =
+ (T) Convert.ChangeType(
+ json.Substring(tokens[i].start, tokens[i].end - tokens[i].start),
+ typeof(T));
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ i++;
+ }
+
+ i--;
+ break;
+ case jsmntype_t.JSMN_OBJECT:
+ break;
+ case jsmntype_t.JSMN_UNDEFINED:
+ break;
+ case jsmntype_t.JSMN_STRING:
+ break;
+ case jsmntype_t.JSMN_PRIMITIVE:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+ }
+
+ public static unsafe void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info)
+ {
+ const int count = 20;
+ jsmntok_t* tokens = stackalloc jsmntok_t[count];
+ var found = 0;
+ fixed (char* pjson = json)
+ {
+ jsmn_parser parser;
+ jsmn_c.init(&parser);
+ found = jsmn_c.jsmn_parse(&parser, pjson, json.Length, tokens, count);
+ }
+
+ const string idField = "id";
+ const string paramsField = "params";
+
+ for (int i = 0; i < found; i++)
+ {
+ var tokSz = tokens[i].end - tokens[i].start;
+ var current = tokens[i];
+ var currentval = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start);
+ if (tokSz == idField.Length && String.Compare(idField, 0, json, tokens[i].start, tokSz) == 0)
+ {
+ i++;
+ rawId = json.Substring(tokens[i].start, tokens[i].end - tokens[i].start);
+ }
+
+ else if (tokSz == paramsField.Length && String.Compare(paramsField, 0, json, tokens[i].start, tokSz) == 0)
+ {
+ i++;
+ switch (tokens[i].type)
+ {
+ case jsmntype_t.JSMN_ARRAY:
+ var level = i;
+ i++;
+ while (tokens[i].parent == level)
+ {
+ switch (tokens[i].type)
+ {
+ case jsmntype_t.JSMN_UNDEFINED:
+ break;
+ case jsmntype_t.JSMN_OBJECT:
+ break;
+ case jsmntype_t.JSMN_ARRAY:
+ break;
+ case jsmntype_t.JSMN_STRING:
+ if (i - level == 1)
+ functionParameters.Item1 =
+ (T1) Convert.ChangeType(
+ json.Substring(tokens[i].start, tokens[i].end - tokens[i].start),
+ typeof(T1));
+ if (i - level == 2)
+ functionParameters.Item2 =
+ (T2) Convert.ChangeType(
+ json.Substring(tokens[i].start, tokens[i].end - tokens[i].start),
+ typeof(T2));
+ break;
+ case jsmntype_t.JSMN_PRIMITIVE:
+ if (i - level == 1)
+ functionParameters.Item1 =
+ (T1) Convert.ChangeType(
+ json.Substring(tokens[i].start, tokens[i].end - tokens[i].start),
+ typeof(T1));
+ if (i - level == 2)
+ functionParameters.Item2 =
+ (T2) Convert.ChangeType(
+ json.Substring(tokens[i].start, tokens[i].end - tokens[i].start),
+ typeof(T2));
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ i++;
+ }
+
+ i--;
+ break;
+ case jsmntype_t.JSMN_OBJECT:
+ break;
+ case jsmntype_t.JSMN_UNDEFINED:
+ break;
+ case jsmntype_t.JSMN_STRING:
+ break;
+ case jsmntype_t.JSMN_PRIMITIVE:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+ }
+ }
+
+ internal static unsafe class jsmn_c
+ {
+ /**
+ * Allocates a fresh unused token from the token pull.
+ */
+ static jsmntok_t* jsmn_alloc_token(jsmn_parser* parser, jsmntok_t* tokens, int num_tokens)
+ {
+ jsmntok_t* tok;
+ if (parser->toknext >= num_tokens)
+ {
+ return null;
+ }
+ tok = &tokens[parser->toknext++];
+ tok->start = tok->end = -1;
+ tok->size = 0;
+
+ tok->parent = -1;
+
+ return tok;
+ }
+
+ /**
+ * Fills token type and boundaries.
+ */
+ static void jsmn_fill_token(jsmntok_t* token, jsmntype_t type, int start, int end)
+ {
+ token->type = type;
+ token->start = start;
+ token->end = end;
+ token->size = 0;
+ }
+
+ /**
+ * Fills next available token with JSON primitive.
+ */
+ static int jsmn_parse_primitive(jsmn_parser* parser, char* js, int len, jsmntok_t* tokens, int num_tokens)
+ {
+ jsmntok_t* token;
+ int start;
+
+ start = parser->pos;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++)
+ {
+ switch (js[parser->pos])
+ {
+ //# ifndef JSMN_STRICT
+ // /* In strict mode primitive must be followed by "," or "}" or "]" */
+ // case ':':
+ //#endif
+ case '\t':
+ case '\r':
+ case '\n':
+ case ' ':
+ case ',':
+ case ']':
+ case '}':
+ goto found;
+ }
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127)
+ {
+ parser->pos = start;
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ }
+ }
+ //# ifdef JSMN_STRICT
+ /* In strict mode primitive must be followed by a comma/object/array */
+ parser->pos = start;
+ return (int)jsmnerr.JSMN_ERROR_PART;
+ //#endif
+
+ found:
+ if (tokens == null)
+ {
+ parser->pos--;
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == null)
+ {
+ parser->pos = start;
+ return (int)jsmnerr.JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, jsmntype_t.JSMN_PRIMITIVE, (int)start, (int)parser->pos);
+ //# ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+ //#endif
+ parser->pos--;
+ return 0;
+ }
+
+ /**
+ * Fills next token with JSON string.
+ */
+ static int jsmn_parse_string(jsmn_parser* parser, char* js, int len, jsmntok_t* tokens, int num_tokens)
+ {
+ jsmntok_t* token;
+
+ int start = (int)parser->pos;
+
+ parser->pos++;
+
+ /* Skip starting quote */
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++)
+ {
+ char c = js[parser->pos];
+
+ /* Quote: end of string */
+ if (c == '\"')
+ {
+ if (tokens == null)
+ {
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == null)
+ {
+ parser->pos = start;
+ return (int)jsmnerr.JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, jsmntype_t.JSMN_STRING, start + 1, parser->pos);
+ //# ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+ //#endif
+ return 0;
+ }
+
+ /* Backslash: Quoted symbol expected */
+ if (c == '\\' && parser->pos + 1 < len)
+ {
+ int i;
+ parser->pos++;
+ switch (js[parser->pos])
+ {
+ /* Allowed escaped symbols */
+ case '\"':
+ case '/':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'r':
+ case 'n':
+ case 't':
+ break;
+ /* Allows escaped symbol \uXXXX */
+ case 'u':
+ parser->pos++;
+ for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++)
+ {
+ /* If it isn't a hex character we have an error */
+ if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102)))
+ { /* a-f */
+ parser->pos = start;
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ }
+ parser->pos++;
+ }
+ parser->pos--;
+ break;
+ /* Unexpected symbol */
+ default:
+ parser->pos = start;
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ }
+ }
+ }
+ parser->pos = start;
+ return (int)jsmnerr.JSMN_ERROR_PART;
+ }
+
+ /**
+ * Parse JSON string and fill tokens.
+ */
+ internal static int jsmn_parse(jsmn_parser* parser, char* js, int len, jsmntok_t* tokens, int num_tokens)
+ {
+ int r;
+ int i;
+ jsmntok_t* token;
+ int count = (int)parser->toknext;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++)
+ {
+ char c;
+ jsmntype_t type;
+
+ c = js[parser->pos];
+ switch (c)
+ {
+ case '{':
+ case '[':
+ count++;
+ if (tokens == null)
+ {
+ break;
+ }
+ token = jsmn_alloc_token(parser, tokens, (int)num_tokens);
+ if (token == null)
+ return (int)jsmnerr.JSMN_ERROR_NOMEM;
+ if (parser->toksuper != -1)
+ {
+ tokens[parser->toksuper].size++;
+ //# ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+ //#endif
+ }
+ token->type = (c == '{' ? jsmntype_t.JSMN_OBJECT : jsmntype_t.JSMN_ARRAY);
+ token->start = parser->pos;
+ parser->toksuper = (int)parser->toknext - 1;
+ break;
+ case '}':
+ case ']':
+ if (tokens == null)
+ break;
+ type = (c == '}' ? jsmntype_t.JSMN_OBJECT : jsmntype_t.JSMN_ARRAY);
+ //# ifdef JSMN_PARENT_LINKS
+ if (parser->toknext < 1)
+ {
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ }
+ token = &tokens[parser->toknext - 1];
+ for (; ; )
+ {
+ if (token->start != -1 && token->end == -1)
+ {
+ if (token->type != type)
+ {
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ }
+ token->end = parser->pos + 1;
+ parser->toksuper = token->parent;
+ break;
+ }
+ if (token->parent == -1)
+ {
+ if (token->type != type || parser->toksuper == -1)
+ {
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ }
+ break;
+ }
+ token = &tokens[token->parent];
+ }
+ //#else
+ // for (i = parser->toknext - 1; i >= 0; i--)
+ // {
+ // token = &tokens[i];
+ // if (token->start != -1 && token->end == -1)
+ // {
+ // if (token->type != type)
+ // {
+ // return jsmnerr.JSMN_ERROR_INVAL;
+ // }
+ // parser->toksuper = -1;
+ // token->end = parser->pos + 1;
+ // break;
+ // }
+ // }
+ // /* Error if unmatched closing bracket */
+ // if (i == -1) return jsmnerr.JSMN_ERROR_INVAL;
+ // for (; i >= 0; i--)
+ // {
+ // token = &tokens[i];
+ // if (token->start != -1 && token->end == -1)
+ // {
+ // parser->toksuper = i;
+ // break;
+ // }
+ // }
+ //#endif
+ break;
+ case '\"':
+ r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != null)
+ tokens[parser->toksuper].size++;
+ break;
+ case '\t':
+ case '\r':
+ case '\n':
+ case ' ':
+ break;
+ case ':':
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case ',':
+ if (tokens != null && parser->toksuper != -1 &&
+ tokens[parser->toksuper].type != jsmntype_t.JSMN_ARRAY &&
+ tokens[parser->toksuper].type != jsmntype_t.JSMN_OBJECT)
+ {
+ //# ifdef JSMN_PARENT_LINKS
+ parser->toksuper = tokens[parser->toksuper].parent;
+ //#else
+ // for (i = parser->toknext - 1; i >= 0; i--)
+ // {
+ // if (tokens[i].type == jsmntype_t.JSMN_ARRAY || tokens[i].type == jsmntype_t.JSMN_OBJECT)
+ // {
+ // if (tokens[i].start != -1 && tokens[i].end == -1)
+ // {
+ // parser->toksuper = i;
+ // break;
+ // }
+ // }
+ // }
+ //#endif
+ }
+ break;
+ //# ifdef JSMN_STRICT
+ /* In strict mode primitives are: numbers and booleans */
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 't':
+ case 'f':
+ case 'n':
+ /* And they must not be keys of the object */
+ if (tokens != null && parser->toksuper != -1)
+ {
+ jsmntok_t* t = &tokens[parser->toksuper];
+ if (t->type == jsmntype_t.JSMN_OBJECT ||
+ (t->type == jsmntype_t.JSMN_STRING && t->size != 0))
+ {
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ }
+ }
+ //#else
+ // /* In non-strict mode every unquoted value is a primitive */
+ // default:
+ //#endif
+ r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != null)
+ tokens[parser->toksuper].size++;
+ break;
+
+ //# ifdef JSMN_STRICT
+ /* Unexpected char in strict mode */
+ default:
+ return (int)jsmnerr.JSMN_ERROR_INVAL;
+ //#endif
+ }
+ }
+
+ if (tokens != null)
+ {
+ for (i = parser->toknext - 1; i >= 0; i--)
+ {
+ /* Unmatched opened object or array */
+ if (tokens[i].start != -1 && tokens[i].end == -1)
+ {
+ return (int)jsmnerr.JSMN_ERROR_PART;
+ }
+ }
+ }
+
+ return count;
+ }
+
+ /**
+ * Creates a new parser based over a given buffer with an array of tokens
+ * available.
+ */
+ internal static void init(jsmn_parser* parser)
+ {
+ parser->pos = 0;
+ parser->toknext = 0;
+ parser->toksuper = -1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj
new file mode 100644
index 0000000..26d67c3
--- /dev/null
+++ b/AustinHarris.JsonRpc.Newtonsoft/AustinHarris.JsonRpc.Newtonsoft.csproj
@@ -0,0 +1,15 @@
+
+
+ netstandard2.1
+
+
+ false
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs
new file mode 100644
index 0000000..b464ab7
--- /dev/null
+++ b/AustinHarris.JsonRpc.Newtonsoft/JsonRequest.cs
@@ -0,0 +1,26 @@
+using Newtonsoft.Json;
+
+namespace AustinHarris.JsonRpc.Newtonsoft
+{
+ ///
+ /// Represents a JsonRpc request
+ ///
+ [JsonObject(MemberSerialization.OptIn)]
+ public class JsonRequest : IJsonRequest
+ {
+ public JsonRequest()
+ {
+ }
+
+ public JsonRequest(string method, string raw)
+ {
+ Method = method;
+ Raw = raw;
+ }
+
+ [JsonProperty("method")]
+ public string Method { get; set; }
+
+ public string Raw { get; set; }
+ }
+}
diff --git a/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs
new file mode 100644
index 0000000..c10ce87
--- /dev/null
+++ b/AustinHarris.JsonRpc.Newtonsoft/JsonResponseErrorObject.cs
@@ -0,0 +1,48 @@
+using System;
+using Newtonsoft.Json;
+
+namespace AustinHarris.JsonRpc.Newtonsoft
+{
+ ///
+ /// 5.1 Error object
+ ///
+ /// When a rpc call encounters an error, the Response Object MUST contain the error member with a value that is a Object with the following members:
+ /// codeA Number that indicates the error type that occurred.
+ /// This MUST be an integer.messageA String providing a short description of the error.
+ /// The message SHOULD be limited to a concise single sentence.dataA Primitive or Structured value that contains additional information about the error.
+ /// This may be omitted.
+ /// The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).
+ /// The error codes from and including -32768 to -32000 are reserved for pre-defined errors. Any code within this range, but not defined explicitly below is reserved for future use. The error codes are nearly the same as those suggested for XML-RPC at the following url: http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
+ ///
+ /// code message meaning
+ ///
+ /// -32700 Parse error Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text.
+ /// -32600 Invalid Request The JSON sent is not a valid Request object.
+ /// -32601 Method not found The method does not exist / is not available.
+ /// -32602 Invalid params Invalid method parameter(s).
+ /// -32603 Internal error Internal JSON-RPC error.
+ /// -32000 to -32099 Server error Reserved for implementation-defined server-errors.
+ ///
+ /// The remainder of the space is available for application defined errors.
+ ///
+ [Serializable]
+ [JsonObject(MemberSerialization.OptIn)]
+ public class JsonRpcException : System.Exception, IJsonRpcException
+ {
+ [JsonProperty]
+ public int Code { get; set; }
+
+ [JsonProperty]
+ public string Message { get; set; }
+
+ [JsonProperty]
+ public object Data { get; set; }
+
+ public JsonRpcException(int code, string message, object data)
+ {
+ this.Code = code;
+ this.Message = message;
+ this.Data = data;
+ }
+ }
+}
diff --git a/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs
new file mode 100644
index 0000000..5a03aa8
--- /dev/null
+++ b/AustinHarris.JsonRpc.Newtonsoft/ObjectFactory.cs
@@ -0,0 +1,486 @@
+using System;
+using System.Buffers;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System.Linq;
+using AustinHarris.JsonRpc.Jsmn;
+
+namespace AustinHarris.JsonRpc.Newtonsoft
+{
+ public class ObjectFactory : IObjectFactory
+ {
+ public IJsonRpcException CreateException(int code, string message, object data)
+ {
+ return new JsonRpcException(code, message, data);
+ }
+
+ public object DeserializeJson(string json, Type type)
+ {
+ return JsonConvert.DeserializeObject(json, type);
+ }
+
+ public IJsonRequest CreateRequest()
+ {
+ return new JsonRequest();
+ }
+// // JSON.Net implementation
+// public string MethodName(string json)
+// {
+// JsonTextReader reader = new JsonTextReader(new StringReader(json));
+// using (reader)
+// while (reader.Read())
+// {
+// if (reader.TokenType == JsonToken.PropertyName)
+// {
+// var name = (string)reader.Value;
+// if (name == "method")
+// {
+// reader.Read();
+// return (string)reader.Value;
+// }
+// continue;
+// }
+// }
+// return String.Empty;
+// }
+
+ // JSMN implementation
+ private static string METHOD = "method";
+ public string MethodName(string json)
+ {
+ string value;
+ if (jsmn.parseFirstField(json,METHOD,out value))
+ {
+ return value;
+ }
+
+ throw new KeyNotFoundException(METHOD);
+ }
+
+ const string envelopeResult1 = "{\"jsonrpc\":\"2.0\",\"result\":";
+ const string envelopeError1 = "{\"jsonrpc\":\"2.0\",\"error\":";
+ const string envelope2 = ",\"id\":";
+ const string envelope3 = "}";
+ static int LenEnvelopeResult = envelopeResult1.Length + envelope2.Length + envelope3.Length;
+ static int LenEnvelopeError = envelopeError1.Length + envelope2.Length + envelope3.Length;
+
+ public string ToJsonRpcResponse(ref InvokeResult response)
+ {
+ if (String.IsNullOrEmpty(response.SerializedError))
+ {
+ var respLen = response.SerializedResult.Length +
+ (response.SerializedId !=null ? response.SerializedId.Length : 0)
+ + LenEnvelopeResult;
+ string outs = string.Create(respLen, response, (span, result) =>
+ {
+ var newC = 0;
+ for (int i = 0; i < envelopeResult1.Length; i++)
+ {
+ span[newC++] = envelopeResult1[i];
+ }
+
+ for (int i = 0; i < result.SerializedResult.Length; i++)
+ {
+ span[newC++] = result.SerializedResult[i];
+ }
+
+ for (int i = 0; i < envelope2.Length; i++)
+ {
+ span[newC++] = envelope2[i];
+ }
+
+ if (result.SerializedId != null)
+ {
+ for (int i = 0; i < result.SerializedId.Length; i++)
+ {
+ span[newC++] = result.SerializedId[i];
+ }
+ }
+
+ for (int i = 0; i < envelope3.Length; i++)
+ {
+ span[newC++] = envelope3[i];
+ }
+ });
+ return outs;
+ }
+ else
+ {
+ var respLen = response.SerializedError.Length +
+ response.SerializedId.Length
+ + LenEnvelopeError;
+
+ string outs = string.Create(respLen, response, (span, result) =>
+ {
+ var newC = 0;
+ for (int i = 0; i < envelopeError1.Length; i++)
+ {
+ span[newC++] = envelopeError1[i];
+ }
+
+ for (int i = 0; i < result.SerializedError.Length; i++)
+ {
+ span[newC++] = result.SerializedError[i];
+ }
+
+ for (int i = 0; i < envelope2.Length; i++)
+ {
+ span[newC++] = envelope2[i];
+ }
+
+ for (int i = 0; i < result.SerializedId.Length; i++)
+ {
+ span[newC++] = result.SerializedId[i];
+ }
+
+ for (int i = 0; i < envelope3.Length; i++)
+ {
+ span[newC++] = envelope3[i];
+ }
+ });
+ return outs;
+
+ }
+ }
+ static JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
+ public string Serialize(T data)
+ {
+ return JsonConvert.SerializeObject(data, jsonSerializerSettings);
+ }
+
+ public IJsonRequest[] DeserializeRequests(string requests)
+ {
+ return JsonConvert.DeserializeObject(requests);
+ }
+
+ public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info)
+ {
+ jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info);
+ }
+
+ public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref string rawId,
+ KeyValuePair[] info)
+ {
+ jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info);
+ }
+
+// public void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] info)
+// {
+// var prop = new Stack();
+// var ptype = String.Empty;
+// JsonTextReader reader = new JsonTextReader(new StringReader(json));
+// var pidx = 0;
+// while (reader.Read())
+// {
+// if (reader.Value != null)
+// {
+// if (reader.TokenType == JsonToken.PropertyName)
+// {
+// prop.Push((string)reader.Value);
+// continue;
+// }
+// else if (prop.Peek() == "jsonrpc" && prop.Count == 1)
+// {
+// prop.Pop();
+// continue;
+// }
+// else if (prop.Peek() == "method" && prop.Count == 1)
+// {
+// prop.Pop();
+// continue;
+// }
+// else if (prop.Peek() == "id" && prop.Count == 1)
+// {
+// rawId = reader.Value.ToString();
+// prop.Pop();
+// continue;
+// }
+// else
+// {
+// if (ptype == "Array")
+// {
+// if (reader.TokenType == JsonToken.Null)
+// functionParameters.Item1 = default(T);
+// else
+// functionParameters.Item1 = new JValue(reader.Value).ToObject();
+// pidx++;
+// }
+// else if (ptype == "Object")
+// {
+// var propName = prop.Pop();
+// for (int i = 0; i < info.Length; i++)
+// {
+// if (info[i].Key == propName)
+// {
+// if (reader.TokenType == JsonToken.Null)
+// functionParameters.Item1 = default(T);
+// else
+// functionParameters.Item1 = new JValue(reader.Value).ToObject();
+// }
+// }
+// }
+// }
+// }
+// else
+// {
+// if (prop.Count > 0 && prop.Peek() == "params")
+// {
+// if (reader.TokenType == JsonToken.StartArray)
+// {
+// ptype = "Array";
+// }
+// else if (reader.TokenType == JsonToken.StartObject)
+// {
+// ptype = "Object";
+// }
+// else if (reader.TokenType == JsonToken.EndArray
+// || reader.TokenType == JsonToken.EndObject)
+// {
+// prop.Pop();
+// continue;
+// }
+// }
+// }
+// }
+// }
+
+// public void DeserializeJsonRef(string json, ref (T1, T2) functionParameters, ref string rawId, KeyValuePair[] info)
+// {
+// var prop = new Stack();
+// var ptype = String.Empty;
+// JsonTextReader reader = new JsonTextReader(new StringReader(json));
+// var pidx = 0;
+// while (reader.Read())
+// {
+// if (reader.Value != null)
+// {
+// if (reader.TokenType == JsonToken.PropertyName)
+// {
+// prop.Push((string)reader.Value);
+// continue;
+// }
+// else if (prop.Peek() == "jsonrpc" && prop.Count == 1)
+// {
+// prop.Pop();
+// continue;
+// }
+// else if (prop.Peek() == "method" && prop.Count == 1)
+// {
+// prop.Pop();
+// continue;
+// }
+// else if (prop.Peek() == "id" && prop.Count == 1)
+// {
+// rawId = reader.Value.ToString();
+// prop.Pop();
+// continue;
+// }
+// else
+// {
+// if (ptype == "Array")
+// {
+// if (pidx == 0)
+// {
+// if (reader.TokenType == JsonToken.Null)
+// functionParameters.Item1 = default(T1);
+// else
+// functionParameters.Item1 = new JValue(reader.Value).ToObject();
+// }
+// else
+// {
+// if (reader.TokenType == JsonToken.Null)
+// functionParameters.Item2 = default(T2);
+// else
+// functionParameters.Item2 = new JValue(reader.Value).ToObject();
+// }
+// pidx++;
+// }
+// else if (ptype == "Object")
+// {
+// var propName = prop.Pop();
+// for (int i = 0; i < info.Length; i++)
+// {
+// if (info[i].Key == propName)
+// {
+// if (i == 0)
+// {
+// if (reader.TokenType == JsonToken.Null)
+// functionParameters.Item1 = default(T1);
+// else
+// functionParameters.Item1 = new JValue(reader.Value).ToObject();
+// }
+// else
+// {
+// if (reader.TokenType == JsonToken.Null)
+// functionParameters.Item2 = default(T2);
+// else
+// functionParameters.Item2 = new JValue(reader.Value).ToObject();
+// }
+// }
+// }
+// }
+// }
+// }
+// else
+// {
+// if (prop.Count > 0 && prop.Peek() == "params")
+// {
+// if (reader.TokenType == JsonToken.StartArray)
+// {
+// ptype = "Array";
+// }
+// else if (reader.TokenType == JsonToken.StartObject)
+// {
+// ptype = "Object";
+// }
+// else if (reader.TokenType == JsonToken.EndArray
+// || reader.TokenType == JsonToken.EndObject)
+// {
+// prop.Pop();
+// continue;
+// }
+// }
+// }
+// }
+// }
+
+ public void DeserializeJsonRef(string json, ref (T1, T2, T3) functionParameters, ref string rawId, KeyValuePair[] info)
+ {
+ var prop = new Stack();
+ var ptype = String.Empty;
+ JsonTextReader reader = new JsonTextReader(new StringReader(json));
+ var pidx = 0;
+ while (reader.Read())
+ {
+ if (reader.Value != null)
+ {
+ if (reader.TokenType == JsonToken.PropertyName)
+ {
+ prop.Push((string)reader.Value);
+ continue;
+ }
+ else if (prop.Peek() == "jsonrpc" && prop.Count == 1)
+ {
+ prop.Pop();
+ continue;
+ }
+ else if (prop.Peek() == "method" && prop.Count == 1)
+ {
+ prop.Pop();
+ continue;
+ }
+ else if (prop.Peek() == "id" && prop.Count == 1)
+ {
+ rawId = reader.Value.ToString();
+ prop.Pop();
+ continue;
+ }
+ else
+ {
+ if (ptype == "Array")
+ {
+ if (pidx == 0)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ functionParameters.Item1 = default(T1);
+ else
+ functionParameters.Item1 = new JValue(reader.Value).ToObject();
+ }
+ else if(pidx == 1)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ functionParameters.Item2 = default(T2);
+ else
+ functionParameters.Item2 = new JValue(reader.Value).ToObject();
+ }
+ else
+ {
+ if (reader.TokenType == JsonToken.Null)
+ functionParameters.Item3 = default(T3);
+ else
+ functionParameters.Item3 = new JValue(reader.Value).ToObject();
+ }
+ pidx++;
+ }
+ else if (ptype == "Object")
+ {
+ var propName = prop.Pop();
+ for (int i = 0; i < info.Length; i++)
+ {
+ if (info[i].Key == propName)
+ {
+ if (i == 0)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ functionParameters.Item1 = default(T1);
+ else
+ functionParameters.Item1 = new JValue(reader.Value).ToObject();
+ }
+ else if(i == 1)
+ {
+ if (reader.TokenType == JsonToken.Null)
+ functionParameters.Item2 = default(T2);
+ else
+ functionParameters.Item2 = new JValue(reader.Value).ToObject();
+ }
+ else
+ {
+ if (reader.TokenType == JsonToken.Null)
+ functionParameters.Item3 = default(T3);
+ else
+ functionParameters.Item3 = new JValue(reader.Value).ToObject();
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (prop.Count > 0 && prop.Peek() == "params")
+ {
+ if (reader.TokenType == JsonToken.StartArray)
+ {
+ ptype = "Array";
+ }
+ else if (reader.TokenType == JsonToken.StartObject)
+ {
+ ptype = "Object";
+ }
+ else if (reader.TokenType == JsonToken.EndArray
+ || reader.TokenType == JsonToken.EndObject)
+ {
+ prop.Pop();
+ continue;
+ }
+ }
+ }
+ }
+ }
+
+ public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DeserializeJsonRef(string json, ref (T1, T2, T3, T4, T5, T6, T7) functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ }
+}
diff --git a/AustinHarris.JsonRpc.Standard/Attributes.cs b/AustinHarris.JsonRpc.Standard/Attributes.cs
new file mode 100644
index 0000000..1592511
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/Attributes.cs
@@ -0,0 +1,50 @@
+using System;
+
+namespace AustinHarris.JsonRpc
+{
+ ///
+ /// Required to expose a method to the JsonRpc service.
+ ///
+ [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
+ public sealed class JsonRpcMethodAttribute : Attribute
+ {
+ readonly string jsonMethodName;
+
+ ///
+ /// Required to expose a method to the JsonRpc service.
+ ///
+ /// Lets you specify the method name as it will be referred to by JsonRpc.
+ public JsonRpcMethodAttribute(string jsonMethodName = "")
+ {
+ this.jsonMethodName = jsonMethodName;
+ }
+
+ 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/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj
new file mode 100644
index 0000000..7832d1f
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/AustinHarris.JsonRpc.Standard.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.1
+
+
+
+ false
+
+
+
diff --git a/AustinHarris.JsonRpc.Standard/Config.cs b/AustinHarris.JsonRpc.Standard/Config.cs
new file mode 100644
index 0000000..45eab83
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/Config.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Threading.Tasks;
+
+namespace AustinHarris.JsonRpc
+{
+ ///
+ /// The PreProcessHandler is called after the request has been parsed and prior to calling the associated method on the JsonRpcService.
+ /// If any non-null result is returned from the PreProcessHandler, the operation is aborted and the error is returned to the caller.
+ ///
+ /// The jsonRpc Request that is pending processing.
+ /// 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 IJsonRpcException PreProcessHandler(IJsonRequest 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 IJsonRpcException PostProcessHandler(IJsonRequest request, ref InvokeResult response, object context);
+
+ ///
+ /// Global configurations for JsonRpc
+ ///
+ public static class Config
+ {
+ ///
+ /// Sets the object factory to be used.
+ ///
+ ///
+ public static void ConfigureFactory(IObjectFactory factory)
+ {
+ Handler.Configure(factory);
+ }
+
+ ///
+ /// Sets the the PreProcessing Handler on the default session.
+ ///
+ ///
+ 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
+ ///
+ ///
+ ///
+ public static void SetBeforeProcessHandler(string sessionId, PreProcessHandler handler)
+ {
+ Handler.GetSessionHandler(sessionId).SetPreProcessHandler(handler);
+ }
+
+ ///
+ /// For exceptions thrown after the routed method has been called.
+ /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client.
+ /// You are able to modify the error that is returned inside the provided handler.
+ ///
+ ///
+ public static void SetErrorHandler(Func handler)
+ {
+ Handler.DefaultHandler.SetErrorHandler(handler);
+ }
+
+ ///
+ /// For exceptions thrown after the routed method has been called.
+ /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client.
+ /// You are able to modify the error that is returned inside the provided handler.
+ ///
+ ///
+ ///
+ public static void SetErrorHandler(string sessionId, Func handler)
+ {
+ Handler.GetSessionHandler(sessionId).SetErrorHandler(handler);
+ }
+
+ ///
+ /// For exceptions thrown during parsing and prior to a routed method being called.
+ /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client.
+ /// You are able to modify the error that is returned inside the provided handler.
+ ///
+ ///
+ public static void SetParseErrorHandler(Func handler)
+ {
+ Handler.DefaultHandler.SetParseErrorHandler(handler);
+ }
+
+ ///
+ /// For exceptions thrown during parsing and prior to a routed method being called.
+ /// Allows you to specify an error handler that will be invoked prior to returning the JsonResponse to the client.
+ /// You are able to modify the error that is returned inside the provided handler.
+ ///
+ ///
+ ///
+ public static void SetParseErrorHandler(string sessionId, Func handler)
+ {
+ Handler.GetSessionHandler(sessionId).SetParseErrorHandler(handler);
+ }
+ }
+}
diff --git a/AustinHarris.JsonRpc.Standard/Handler.cs b/AustinHarris.JsonRpc.Standard/Handler.cs
new file mode 100644
index 0000000..5719460
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/Handler.cs
@@ -0,0 +1,325 @@
+namespace AustinHarris.JsonRpc
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using System.Collections.Concurrent;
+ using System.Threading;
+
+ public class Handler
+ {
+ #region Members
+ 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;
+ internal static IObjectFactory _objectFactory;
+ private static volatile string _defaultSessionId;
+ #endregion
+
+ #region Constructors
+
+ static Handler()
+ {
+ //current = new Handler(Guid.NewGuid().ToString());
+ _defaultSessionId = Guid.NewGuid().ToString();
+ _sessionHandlersMaster = new ConcurrentDictionary();
+ }
+
+ private Handler(string sessionId)
+ {
+ SessionId = sessionId;
+ this.MetaData = new SMD();
+ if(_objectFactory == null)
+ {
+ throw new InvalidOperationException("Configure must be called before Handler is created.");
+ }
+ }
+
+ public static void Configure(IObjectFactory factory)
+ {
+ _objectFactory = factory ?? throw new ArgumentNullException("factory");
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Returns the SessionID of the default session
+ ///
+ ///
+ public static string DefaultSessionId() { return _defaultSessionId; }
+
+ ///
+ /// Gets a specific session
+ ///
+ /// The sessionId of the handler you want to retrieve.
+ ///
+ public static Handler GetSessionHandler(string 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
+ ///
+ /// The default Session Handler
+ public static Handler GetSessionHandler()
+ {
+ return GetSessionHandler(_defaultSessionId);
+ }
+
+ ///
+ /// Removes and clears the Handler with the specific sessionID from the registry of Handlers
+ ///
+ ///
+ public static void DestroySession(string sessionId)
+ {
+ _sessionHandlersMaster.TryRemove(sessionId, out Handler h);
+ Interlocked.Increment(ref _sessionHandlerMasterVersion);
+ h.MetaData.Services.Clear();
+ }
+ ///
+ /// Removes and clears the current Handler from the registry of Handlers
+ ///
+ public void Destroy()
+ {
+ DestroySession(SessionId);
+ }
+
+ ///
+ /// Gets the default session handler
+ ///
+ public static Handler DefaultHandler { get { return GetSessionHandler(_defaultSessionId); } }
+
+ ///
+ /// The sessionID of this Handler
+ ///
+ public string SessionId { get; private set; }
+
+
+
+ ///
+ /// Provides access to a context specific to each JsonRpc method invocation.
+ /// Warning: Must be called from within the execution context of the jsonRpc Method to return the context
+ ///
+ ///
+ public static object RpcContext()
+ {
+ return __currentRpcContext;
+ }
+
+ [ThreadStatic]
+ static IJsonRpcException __currentRpcException;
+ ///
+ /// Allows you to set the exception used in in the JsonRpc response.
+ /// Warning: Must be called from the same thread as the jsonRpc method.
+ ///
+ ///
+ public static void RpcSetException(IJsonRpcException exception)
+ {
+ __currentRpcException = exception;
+ }
+ public static IJsonRpcException RpcGetAndRemoveRpcException()
+ {
+ var ex = __currentRpcException;
+ __currentRpcException = null ;
+ return ex;
+ }
+
+ private AustinHarris.JsonRpc.PreProcessHandler externalPreProcessingHandler;
+ private AustinHarris.JsonRpc.PostProcessHandler externalPostProcessingHandler;
+ private Func externalErrorHandler;
+ private Func parseErrorHandler;
+ #endregion
+
+ ///
+ /// This metadata contains all the types and mappings of all the methods in this handler. Warning: Modifying this directly could cause your handler to no longer function.
+ ///
+ public SMD MetaData { get; set; }
+
+ #region Public Methods
+
+ ///
+ /// Allows you to register all the functions on a Pojo Type that have been attributed as [JsonRpcMethod] to the specified sessionId
+ ///
+ /// The session to register against
+ /// The instance containing JsonRpcMethods to register
+ public static void RegisterInstance(string sessionID, object instance)
+ {
+ ServiceBinder.BindService(sessionID, instance);
+ }
+
+ ///
+ /// 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);
+ }
+
+ public void UnRegisterFunction(string methodName)
+ {
+ MetaData.Services.Remove(methodName);
+ }
+
+ public void SetPreProcessHandler(AustinHarris.JsonRpc.PreProcessHandler handler)
+ {
+ externalPreProcessingHandler = handler;
+ }
+
+ public void SetPostProcessHandler(AustinHarris.JsonRpc.PostProcessHandler handler)
+ {
+ externalPostProcessingHandler = handler;
+ }
+
+ ///
+ /// Invokes a method to handle a JsonRpc request.
+ ///
+ /// JsonRpc Request to be processed
+ /// Optional context that will be available from within the jsonRpcMethod.
+ ///
+ public void Handle(IJsonRequest Rpc, ref InvokeResult response, Object RpcContext = null)
+ {
+ AddRpcContext(RpcContext);
+
+ var preProcessingException = PreProcess(Rpc, RpcContext);
+ if (preProcessingException != null)
+ {
+ response.SerializedError = _objectFactory.Serialize(preProcessingException);
+ //callback is called - if it is empty then nothing will be done
+ //return response always- if callback is empty or not
+
+ return ;
+ }
+
+ if (this.MetaData.Services.TryGetValue(Rpc.Method, out SMDService metadata))
+ {
+ }
+ else if (metadata == null)
+ {
+ response.SerializedError = _objectFactory.Serialize(_objectFactory.CreateException(-32601, "Method not found", "The method does not exist / is not available."));
+ return;
+ }
+
+ try
+ {
+ var results = metadata.Invoke(_objectFactory, Rpc.Raw);
+ response.SerializedResult = results.Item1;
+ response.SerializedId = results.Item2;
+ var contextException = RpcGetAndRemoveRpcException();
+
+ if (contextException != null)
+ {
+ response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, contextException));
+ }
+ return ;
+ }
+ catch (Exception ex)
+ {
+ if (ex is TargetParameterCountException)
+ {
+ response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, _objectFactory.CreateException(-32602, "Invalid params", ex)));
+ }
+ else if (ex is IJsonRpcException)
+ {
+ response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, ex as IJsonRpcException));
+ }
+ else if (ex.InnerException != null && ex.InnerException is IJsonRpcException)
+ {
+ response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, ex.InnerException as IJsonRpcException));
+ }
+ else if (ex.InnerException != null)
+ {
+ response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex.InnerException)));
+ }
+ else
+ {
+ response.SerializedError = _objectFactory.Serialize(ProcessException(Rpc, _objectFactory.CreateException(-32603, "Internal Error", ex)));
+ }
+ return;
+ }
+ finally
+ {
+ RemoveRpcContext();
+ }
+ }
+ #endregion
+
+ [ThreadStatic]
+ static object __currentRpcContext;
+ private void AddRpcContext(object RpcContext)
+ {
+ __currentRpcContext = RpcContext;
+ }
+ private void RemoveRpcContext()
+ {
+ __currentRpcContext = null;
+ }
+
+ private IJsonRpcException ProcessException(IJsonRequest req, IJsonRpcException ex)
+ {
+ if (externalErrorHandler != null)
+ return externalErrorHandler(req, ex);
+ return ex;
+ }
+ internal IJsonRpcException ProcessParseException(string req, IJsonRpcException ex)
+ {
+ if (parseErrorHandler != null)
+ return parseErrorHandler(req, ex);
+ return ex;
+ }
+ internal void SetErrorHandler(Func handler)
+ {
+ externalErrorHandler = handler;
+ }
+ internal void SetParseErrorHandler(Func handler)
+ {
+ parseErrorHandler = handler;
+ }
+
+ private IJsonRpcException PreProcess(IJsonRequest request, object context)
+ {
+ return externalPreProcessingHandler == null ? null : externalPreProcessingHandler(request, context);
+ }
+
+ internal void PostProcess(IJsonRequest request, ref InvokeResult response, object context)
+ {
+ if (externalPostProcessingHandler != null)
+ {
+ try
+ {
+ externalPostProcessingHandler(request,ref response, context);
+ }
+ catch (Exception ex)
+ {
+ response.SerializedError = _objectFactory.Serialize( ProcessException(request, _objectFactory.CreateException(-32603, "Internal Error", ex)) );
+ }
+ }
+ }
+
+ }
+
+}
+
diff --git a/AustinHarris.JsonRpc.Standard/IJsonRequest.cs b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs
new file mode 100644
index 0000000..1b6919f
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/IJsonRequest.cs
@@ -0,0 +1,14 @@
+namespace AustinHarris.JsonRpc
+{
+ public interface IJsonRequest
+ {
+ string Raw { get; set; }
+ string Method { get; set; }
+ }
+
+ public interface IJsonRequestFactory
+ {
+ IJsonRequest CreateRequest();
+ IJsonRequest[] DeserializeRequests(string requests);
+ }
+}
\ No newline at end of file
diff --git a/AustinHarris.JsonRpc.Standard/IJsonResponse.cs b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs
new file mode 100644
index 0000000..7b0a50f
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/IJsonResponse.cs
@@ -0,0 +1,9 @@
+namespace AustinHarris.JsonRpc
+{
+ public struct InvokeResult
+ {
+ public string SerializedError;
+ public string SerializedId;
+ public string SerializedResult;
+ }
+}
\ No newline at end of file
diff --git a/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs b/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs
new file mode 100644
index 0000000..100ac60
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/IJsonRpcException.cs
@@ -0,0 +1,13 @@
+namespace AustinHarris.JsonRpc
+{
+ public interface IJsonRpcException
+ {
+ int Code { get; set; }
+ object Data { get; set; }
+ string Message { get; set; }
+ }
+ public interface IJsonRpcExceptionFactory
+ {
+ IJsonRpcException CreateException(int code, string message, object data);
+ }
+}
\ No newline at end of file
diff --git a/AustinHarris.JsonRpc.Standard/IObjectFactory.cs b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs
new file mode 100644
index 0000000..9c23727
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/IObjectFactory.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+
+namespace AustinHarris.JsonRpc
+{
+ public interface IObjectFactory : IJsonRpcExceptionFactory, IJsonRequestFactory
+ {
+ string Serialize(T data);
+ string ToJsonRpcResponse(ref InvokeResult response);
+ object DeserializeJson(string json, Type type);
+ string MethodName(string json);
+
+ void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo);
+ void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo);
+ void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo);
+ void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo);
+ void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo);
+ void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo);
+ void DeserializeJsonRef(string json, ref ValueTuple functionParameters, ref string rawId, KeyValuePair[] functionParameterInfo);
+ }
+}
\ No newline at end of file
diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs b/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs
new file mode 100644
index 0000000..597a81f
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/JsonRpcContext.cs
@@ -0,0 +1,39 @@
+namespace AustinHarris.JsonRpc
+{
+ ///
+ /// Provides access to a context specific to each JsonRpc method invocation.
+ /// This is a convienence class that wraps calls to Context specific methods on AustinHarris.JsonRpc.Handler
+ ///
+ public class JsonRpcContext
+ {
+ private JsonRpcContext(object value)
+ {
+ Value = value;
+ }
+
+ ///
+ /// The data associated with this context.
+ ///
+ public object Value { get; private set; }
+
+ ///
+ /// 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 to function.
+ ///
+ ///
+ public static void SetException(IJsonRpcException exception)
+ {
+ Handler.RpcSetException(exception);
+ }
+
+
+ ///
+ /// Must be called from within the execution context of the jsonRpc Method to return the context
+ ///
+ ///
+ public static JsonRpcContext Current()
+ {
+ return new JsonRpcContext(Handler.RpcContext());
+ }
+ }
+}
diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs
new file mode 100644
index 0000000..6bef5cc
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/JsonRpcProcessor.cs
@@ -0,0 +1,225 @@
+using System;
+using System.Threading.Tasks;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Collections.Concurrent;
+using System.Threading;
+
+namespace AustinHarris.JsonRpc
+{
+ public static class JsonRpcProcessor
+ {
+ static JsonRpcProcessor()
+ {
+ for (int i = 0; i < _privatepool.Length; i++)
+ {
+ _privatepool[i] = new Thread(new ThreadStart(_workPool));
+ _privatepool[i].IsBackground = true;
+ _privatepool[i].Start();
+ }
+ }
+
+ public static void ProcessAsync(JsonRpcStateAsync async, object context = null)
+ {
+ ProcessAsync(Handler.DefaultSessionId(), async, context);
+ }
+
+ public static void ProcessAsync(string sessionId, JsonRpcStateAsync async, object context = null)
+ {
+ ProcessAsync(sessionId, async.JsonRpc, context)
+ .ContinueWith(t =>
+ {
+ async.Result = t.Result;
+ async.SetCompleted();
+ });
+ }
+ public static Task ProcessAsync(string jsonRpc, object context = null)
+ {
+ return ProcessAsync(Handler.DefaultSessionId(), jsonRpc, context);
+ }
+
+ struct ParamBox
+ {
+ public string sessionId;
+ public string jsonRpc;
+ public object context;
+ }
+ struct ParamBox2
+ {
+ public Handler handler;
+ public string jsonRpc;
+ public object context;
+ }
+ struct ParamBox3
+ {
+ public TaskCompletionSource tcs;
+ public Handler handler;
+ public string jsonRpc;
+ public object context;
+ }
+
+ private static TaskFactory _tf = new TaskFactory(TaskScheduler.Default);
+
+ public static Task ProcessAsync(string sessionId, string jsonRpc, object context = null)
+ {
+ ParamBox __pq;
+ __pq.sessionId = sessionId;
+ __pq.jsonRpc = jsonRpc;
+ __pq.context = context;
+
+ return _tf.StartNew((_) =>
+ {
+ return Process(Handler.GetSessionHandler(((ParamBox)_).sessionId), ((ParamBox)_).jsonRpc, ((ParamBox)_).context);
+ }, __pq);
+ }
+ public static Task ProcessAsync(Handler handler, string jsonRpc, object context = null)
+ {
+ ParamBox2 __pq;
+ __pq.handler = handler;
+ __pq.jsonRpc = jsonRpc;
+ __pq.context = context;
+
+ return _tf.StartNew((_) =>
+ {
+ return Process(((ParamBox2)_).handler, ((ParamBox2)_).jsonRpc, ((ParamBox2)_).context);
+ }, __pq);
+ }
+
+ private static BlockingCollection _pendingWork = new BlockingCollection();
+ private static Thread[] _privatepool = new Thread[8];
+ private static void _workPool()
+ {
+ ParamBox3 item;
+ while (true)
+ {
+ item = _pendingWork.Take();
+ item.tcs.SetResult(Process(item.handler, item.jsonRpc, item.context));
+ }
+ }
+
+ public static Task ProcessAsync2(Handler handler, string jsonRpc, object context = null)
+ {
+ var tcs = new TaskCompletionSource();
+ var task = tcs.Task;
+
+ ParamBox3 __pq;
+ __pq.tcs = tcs;
+ __pq.handler = handler;
+ __pq.jsonRpc = jsonRpc;
+ __pq.context = context;
+
+ _pendingWork.Add(__pq);
+ return tcs.Task;
+ }
+
+ [ThreadStatic]
+ static IJsonRequest[] array1 = null;
+
+ public static string Process(Handler handler, string jsonRpc, object jsonRpcContext)
+ {
+ var singleBatch = true;
+
+ IJsonRequest[] batch = null;
+ try
+ {
+ if (IsSingleRpc(jsonRpc))
+ {
+ var name = Handler._objectFactory.MethodName(jsonRpc);
+ if (array1 == null)
+ array1 = new[] { Handler._objectFactory.CreateRequest() };
+ array1[0].Method = name;
+ array1[0].Raw = jsonRpc;
+ batch = array1;
+ }
+ else
+ {
+ batch = Handler._objectFactory.DeserializeRequests(jsonRpc);
+ singleBatch = batch.Length == 1;
+ if (batch.Length == 0)
+ {
+ InvokeResult ir = new InvokeResult
+ {
+ SerializedResult = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(3200, "Invalid Request", "Batch of calls was empty.")))
+ };
+ return Handler._objectFactory.ToJsonRpcResponse( ref ir );
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ InvokeResult ir = new InvokeResult
+ {
+ SerializedResult = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc, Handler._objectFactory.CreateException(-32700, "Parse error", ex)))
+ };
+ return Handler._objectFactory.ToJsonRpcResponse(ref ir);
+ }
+
+ StringBuilder sbResult = null;
+ for (var i = 0; i < batch.Length; i++)
+ {
+ var jsonRequest = batch[i];
+ InvokeResult jsonResponse = new InvokeResult();
+
+ if (jsonRequest == null)
+ {
+ jsonResponse.SerializedError = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc,
+ Handler._objectFactory.CreateException(-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.SerializedError = Handler._objectFactory.Serialize(handler.ProcessParseException(jsonRpc,
+ Handler._objectFactory.CreateException(-32600, "Invalid Request", "Missing property 'method'")));
+ }
+ else
+ {
+ handler.Handle(jsonRequest, ref jsonResponse, jsonRpcContext);
+ handler.PostProcess(jsonRequest, ref jsonResponse, jsonRpcContext);
+
+ if (jsonResponse.SerializedResult == null) continue;
+ }
+
+ // special case optimization for single Item batch
+ if (singleBatch && (jsonResponse.SerializedId != null || jsonResponse.SerializedError != null))
+ {
+ return Handler._objectFactory.ToJsonRpcResponse(ref jsonResponse);
+ }
+ if (jsonResponse.SerializedId == null && jsonResponse.SerializedError == null)
+ {
+ // do nothing
+ sbResult = new StringBuilder(0);
+ }
+ else
+ {
+ // write out the response
+ if (i == 0)
+ {
+ sbResult = new StringBuilder("[");
+ }
+
+ sbResult.Append(Handler._objectFactory.ToJsonRpcResponse(ref jsonResponse));
+ if (i < batch.Length - 1)
+ {
+ sbResult.Append(',');
+ }
+ else if (i == batch.Length - 1)
+ {
+ sbResult.Append(']');
+ }
+ }
+ }
+ return sbResult.ToString();
+ }
+
+ private static bool IsSingleRpc(string json)
+ {
+ for (int i = 0; i < json.Length; i++)
+ {
+ if (json[i] == '{') return true;
+ if (json[i] == '[') return false;
+ }
+ return true;
+ }
+ }
+}
diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcService.cs b/AustinHarris.JsonRpc.Standard/JsonRpcService.cs
new file mode 100644
index 0000000..d8ec961
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/JsonRpcService.cs
@@ -0,0 +1,22 @@
+namespace AustinHarris.JsonRpc
+{
+ ///
+ /// For routing use SessionId
+ ///
+ public abstract class JsonRpcService
+ {
+ protected JsonRpcService()
+ {
+ ServiceBinder.BindService(Handler.DefaultSessionId(), this);
+ }
+
+ ///
+ /// Routing by SessionId
+ ///
+ ///
+ protected JsonRpcService(string sessionID)
+ {
+ ServiceBinder.BindService(sessionID, this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/AustinHarris.JsonRpc.Standard/JsonRpcStateAsync.cs b/AustinHarris.JsonRpc.Standard/JsonRpcStateAsync.cs
new file mode 100644
index 0000000..5869c21
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/JsonRpcStateAsync.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+
+namespace AustinHarris.JsonRpc
+{
+ public class JsonRpcStateAsync : IAsyncResult
+ {
+ public JsonRpcStateAsync(AsyncCallback cb, Object extraData)
+ {
+ this.cb = cb;
+ asyncState = extraData;
+ isCompleted = false;
+ }
+
+ public string JsonRpc { get; set; }
+ public string Result { get; set; }
+
+ private AsyncCallback cb = null;
+ private Object asyncState;
+ public object AsyncState
+ {
+ get
+ {
+ return asyncState;
+ }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ // If this object was not being used solely with ASP.Net this
+ // method would need an implementation. ASP.Net never uses the
+ // event, so it is not implemented here.
+ public WaitHandle AsyncWaitHandle
+ {
+ get
+ {
+ // not supported
+ return null;
+ }
+ }
+
+ private Boolean isCompleted;
+ public bool IsCompleted
+ {
+ get
+ {
+ return isCompleted;
+ }
+ }
+
+ internal void SetCompleted()
+ {
+ isCompleted = true;
+ if (cb != null)
+ {
+ cb(this);
+ }
+ }
+ }
+}
diff --git a/AustinHarris.JsonRpc.Standard/SMDService.cs b/AustinHarris.JsonRpc.Standard/SMDService.cs
new file mode 100644
index 0000000..9a43812
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/SMDService.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace AustinHarris.JsonRpc
+{
+ public class SMD
+ {
+ public Dictionary Services { get; set; }
+
+ public SMD ()
+ {
+ Services = new Dictionary();
+ }
+
+ internal void AddService(string method, Dictionary parameters, Dictionary defaultValues, Delegate dele)
+ {
+ var newService = new SMDService(parameters, defaultValues, dele);
+ Services.Add(method,newService);
+ }
+ }
+
+ public class SMDService
+ {
+ public Delegate dele;
+
+ public KeyValuePair[] Parameters { get; }
+
+ ///
+ /// Stores default values for optional parameters.
+ ///
+ public KeyValuePair[] DefaultValues { get; }
+ public Type Returns { get; }
+
+ ///
+ /// Defines a service method http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html
+ ///
+ ///
+ ///
+ public SMDService(Dictionary parameters, Dictionary defaultValues, Delegate dele)
+ {
+ // TODO: Complete member initialization
+ this.dele = dele;
+ this.Parameters = parameters.Take(parameters.Count-1).ToArray(); // last param is return type similar to Func<,>
+
+ // create the default values storage for optional parameters.
+ this.DefaultValues = defaultValues.ToArray();
+
+ // this is getting the return type from the end of the param list
+ this.Returns = parameters.Values.LastOrDefault();
+
+ _internalFunc = BuildInternalFunc();
+ }
+
+ private Func BuildInternalFunc()
+ {
+ try
+ {
+ var plist = Parameters.Select(x => x.Value).ToArray();
+ Type vtupType;
+ if (plist.Length == 0) vtupType = typeof(ValueTuple);//.MakeGenericType(plist);
+ else if (plist.Length == 1) vtupType = typeof(ValueTuple<>).MakeGenericType(plist);
+ else if (plist.Length == 2) vtupType = typeof(ValueTuple<,>).MakeGenericType(plist);
+ else if (plist.Length == 3) vtupType = typeof(ValueTuple<,,>).MakeGenericType(plist);
+ else if (plist.Length == 4) vtupType = typeof(ValueTuple<,,,>).MakeGenericType(plist);
+ else if (plist.Length == 5) vtupType = typeof(ValueTuple<,,,,>).MakeGenericType(plist);
+ else if (plist.Length == 6) vtupType = typeof(ValueTuple<,,,,,>).MakeGenericType(plist);
+ else if (plist.Length == 7) vtupType = typeof(ValueTuple<,,,,,,>).MakeGenericType(plist);
+ else throw new NotImplementedException("Functions with more then 7 parameters are not supported");
+ // variables
+ var id = Expression.Parameter(typeof(string), "id");
+ var vtup = Expression.Parameter(vtupType, "vtup");
+ var vmeta = Expression.Parameter(typeof(KeyValuePair[]),"vmeta");
+ var vtarget = Expression.Parameter(dele.Target.GetType(), "vtarget");
+ var vreturns = Expression.Parameter(Returns, "vreturns");
+ var vserializedResult = Expression.Parameter(typeof(string), "vserializedResult");
+ var vserializedResultAndId = Expression.Parameter(typeof((string, string)), "vserializedResultAndId");
+ Expression[]>> meta = () => Parameters;
+ Expression> target = () => dele.Target;
+ var meta2 = Expression.Constant(Parameters);
+ var target2 = Expression.Constant(dele.Target);
+ // vtupItems
+ var vtupItems = new Expression[Parameters.Length];
+ for (int i = 0; i < vtupItems.Length; i++)
+ {
+ vtupItems[i] = Expression.PropertyOrField(vtup, "Item" + (i + 1).ToString());
+ }
+ // functions
+ var deser = typeof(IObjectFactory).GetMethods().First(x => {
+ return x.Name == "DeserializeJsonRef" &&
+ x.IsGenericMethod &&
+ x.GetGenericArguments().Length == plist.Length;
+ }).MakeGenericMethod(plist);
+ var serialize = typeof(IObjectFactory).GetMethods().First(x =>
+ {
+ return x.Name == "Serialize" &&
+ x.IsGenericMethod &&
+ x.GetGenericArguments().Length == 1;
+ }).MakeGenericMethod(Returns);
+
+ // parameters
+ var factory = Expression.Parameter(typeof(IObjectFactory), "factory");
+ var json = Expression.Parameter(typeof(string), "json");
+
+ BlockExpression setup = Expression.Block(
+ new[] { id , vmeta, vtarget, vtup, vreturns, vserializedResult, vserializedResultAndId },
+ Expression.Assign(id, Expression.Constant(String.Empty)),
+ Expression.Assign(vtup, Expression.New(vtupType)),
+ Expression.Assign(vmeta, meta2),
+ Expression.Assign(vtarget, Expression.Convert( target2, dele.Target.GetType())),
+ // call deserialize
+ Expression.Call(factory, deser, new Expression[] {
+ json,
+ vtup,
+ id,
+ vmeta
+ }),
+ // call the jsonRpc function with the deserialized parameters
+ Expression.Assign(vreturns, Expression.Call(vtarget, dele.Method, vtupItems)),
+ // serialize the result of the jsonRpc function
+ Expression.Assign(vserializedResult, Expression.Call(factory, serialize, vreturns)),
+ Expression.Assign(Expression.PropertyOrField(vserializedResultAndId, "Item1"), vserializedResult),
+ Expression.Assign(Expression.PropertyOrField(vserializedResultAndId, "Item2"), id),
+ vserializedResultAndId
+ );
+
+ var lambda = Expression.Lambda>(
+ setup,
+ new ParameterExpression[] { factory, json }
+ );
+
+ Console.WriteLine(lambda.ToString());
+
+ return lambda.Compile();
+ }
+ catch (Exception ex)
+ {
+ throw new Exception("parameters: " + Parameters.Length.ToString() +" :: " + String.Join(", ", Parameters.Select(x=> x.Key + " : " + x.Value.Name)), ex);
+ }
+ }
+
+ Func _internalFunc;
+
+ internal (string,string) Invoke(IObjectFactory objectFactory, string jsonRpc)
+ {
+ return _internalFunc(objectFactory, jsonRpc);
+ }
+ }
+}
diff --git a/AustinHarris.JsonRpc.Standard/ServiceBinder.cs b/AustinHarris.JsonRpc.Standard/ServiceBinder.cs
new file mode 100644
index 0000000..45bb077
--- /dev/null
+++ b/AustinHarris.JsonRpc.Standard/ServiceBinder.cs
@@ -0,0 +1,70 @@
+namespace AustinHarris.JsonRpc
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+
+ 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/AustinHarris.JsonRpc.sln b/AustinHarris.JsonRpc.sln
index 858a102..7c23c05 100644
--- a/AustinHarris.JsonRpc.sln
+++ b/AustinHarris.JsonRpc.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.40629.0
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2024
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BBFBBA8A-2F75-422C-ACCD-D05A6EF7244C}"
ProjectSection(SolutionItems) = preProject
@@ -11,15 +11,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpc", "Json-Rpc\AustinHarris.JsonRpc.csproj", "{24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Standard", "AustinHarris.JsonRpc.Standard\AustinHarris.JsonRpc.Standard.csproj", "{01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpc.AspNet", "AustinHarris.JsonRpc.AspNet\AustinHarris.JsonRpc.AspNet.csproj", "{FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestServer_Console.Core", "TestServer_Console.Core\TestServer_Console.Core.csproj", "{FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AustinHarris.JsonRpcTestN", "AustinHarris.JsonRpcTestN\AustinHarris.JsonRpcTestN.csproj", "{8569B076-5A8B-4D6A-B75D-EF75A390AA5F}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Core", ".Net Core", "{9FC11C57-5936-4804-A323-87D5572150EE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestServer_Console", "TestServer_Console\TestServer_Console.csproj", "{31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Net Standard", ".Net Standard", "{CB659139-9876-4850-BBB7-BC48F0B5BA22}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Newtonsoft", "AustinHarris.JsonRpc.Newtonsoft\AustinHarris.JsonRpc.Newtonsoft.csproj", "{216F103E-B492-465E-ABBE-142A1491771C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpcTestN.Core", "AustinHarris.JsonRpcTestN.Core\AustinHarris.JsonRpcTestN.Core.csproj", "{84DBDA32-A467-4902-9577-F7A90986272D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AustinHarris.JsonRpc.Jsmn", "AustinHarris.JsonRpc.Jsmn\AustinHarris.JsonRpc.Jsmn.csproj", "{4D4C9D5F-A675-4CAE-8145-C432D19C15F2}"
EndProject
Global
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
@@ -31,68 +40,109 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|ARM.ActiveCfg = Debug|x86
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|x86.ActiveCfg = Debug|x86
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Debug|x86.Build.0 = Debug|x86
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Any CPU.Build.0 = Release|Any CPU
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|ARM.ActiveCfg = Release|x86
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Mixed Platforms.ActiveCfg = Release|x86
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|Mixed Platforms.Build.0 = Release|x86
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|x86.ActiveCfg = Release|x86
- {24FC1A2A-0BC3-43A7-9BFE-B628C2C4A307}.Release|x86.Build.0 = Release|x86
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Debug|x86.ActiveCfg = Debug|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Any CPU.Build.0 = Release|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|ARM.ActiveCfg = Release|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {FFFDEBBC-93F5-4A22-9EC5-D86A4A792DBB}.Release|x86.ActiveCfg = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|ARM.Build.0 = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|x86.ActiveCfg = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Debug|x86.Build.0 = Debug|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Any CPU.Build.0 = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|ARM.ActiveCfg = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|ARM.Build.0 = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|x86.ActiveCfg = Release|Any CPU
- {8569B076-5A8B-4D6A-B75D-EF75A390AA5F}.Release|x86.Build.0 = Release|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|ARM.Build.0 = Debug|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|x86.ActiveCfg = Debug|x86
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Debug|x86.Build.0 = Debug|x86
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Any CPU.Build.0 = Release|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|ARM.ActiveCfg = Release|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|ARM.Build.0 = Release|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|x86.ActiveCfg = Release|x86
- {31AE59FC-B6F6-4AC7-A7B9-1E07630AE42B}.Release|x86.Build.0 = Release|x86
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|ARM.Build.0 = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Debug|x86.Build.0 = Debug|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|ARM.ActiveCfg = Release|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|ARM.Build.0 = Release|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|x86.ActiveCfg = Release|Any CPU
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0}.Release|x86.Build.0 = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|ARM.Build.0 = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Debug|x86.Build.0 = Debug|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|ARM.ActiveCfg = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|ARM.Build.0 = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|x86.ActiveCfg = Release|Any CPU
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088}.Release|x86.Build.0 = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|ARM.Build.0 = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Debug|x86.Build.0 = Debug|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|ARM.ActiveCfg = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|ARM.Build.0 = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|x86.ActiveCfg = Release|Any CPU
+ {216F103E-B492-465E-ABBE-142A1491771C}.Release|x86.Build.0 = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|ARM.Build.0 = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Debug|x86.Build.0 = Debug|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|ARM.ActiveCfg = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|ARM.Build.0 = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|x86.ActiveCfg = Release|Any CPU
+ {84DBDA32-A467-4902-9577-F7A90986272D}.Release|x86.Build.0 = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|ARM.Build.0 = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Debug|x86.Build.0 = Debug|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|ARM.ActiveCfg = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|ARM.Build.0 = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|x86.ActiveCfg = Release|Any CPU
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {01960B79-0B97-4B74-8D1F-99AFA8A0FDF0} = {CB659139-9876-4850-BBB7-BC48F0B5BA22}
+ {FDFB1B74-FBCA-4317-AFC8-7B8FC5489088} = {9FC11C57-5936-4804-A323-87D5572150EE}
+ {216F103E-B492-465E-ABBE-142A1491771C} = {CB659139-9876-4850-BBB7-BC48F0B5BA22}
+ {84DBDA32-A467-4902-9577-F7A90986272D} = {9FC11C57-5936-4804-A323-87D5572150EE}
+ {4D4C9D5F-A675-4CAE-8145-C432D19C15F2} = {CB659139-9876-4850-BBB7-BC48F0B5BA22}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {895CB7D3-766C-490E-9686-57339AE17D6B}
+ EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = AustinHarris.JsonRpc.vsmdi
EndGlobalSection
diff --git a/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj
new file mode 100644
index 0000000..ca475de
--- /dev/null
+++ b/AustinHarris.JsonRpcTestN.Core/AustinHarris.JsonRpcTestN.Core.csproj
@@ -0,0 +1,17 @@
+
+
+ netcoreapp3.0
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AustinHarris.JsonRpcTestN.Core/Test.cs b/AustinHarris.JsonRpcTestN.Core/Test.cs
new file mode 100644
index 0000000..d760b2b
--- /dev/null
+++ b/AustinHarris.JsonRpcTestN.Core/Test.cs
@@ -0,0 +1,1959 @@
+using Xunit;
+using System;
+using System.Linq;
+using AustinHarris.JsonRpc;
+using System.Text.RegularExpressions;
+using Newtonsoft.Json.Linq;
+
+namespace AustinHarris.JsonRpcTestN.Core
+{
+ public class Poco
+ {
+ 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; }
+ }
+
+ public class Test
+ {
+ [Fact]
+ public void TestCase()
+ {
+ }
+ static object[] services;
+
+ static Test()
+ {
+ Config.ConfigureFactory(new AustinHarris.JsonRpc.Newtonsoft.ObjectFactory());
+ services = new object[] {
+ new CalculatorService()};
+ }
+
+ [Fact]
+ public void TestCanCreateMultipleServicesOfSameTypeInTheirOwnSessions()
+ {
+ string request(int param) => String.Format("{{\"method\":\"add\",\"params\":[{0}],\"id\":1}}", param);
+ string 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.ProcessAsync(i.ToString(), request(10));
+ result.Wait();
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult(10 + i));
+ Assert.Equal(expected1, actual1);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync("this one", request);
+ result.Wait();
+
+
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult);
+ Assert.True(JToken.DeepEquals(expected1, actual1));
+ h.Destroy();
+
+ var result2 = JsonRpcProcessor.ProcessAsync("this one", request);
+ result2.Wait();
+
+ Assert.True(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result)));
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+
+ Assert.Equal(result.Result, expectedResult);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void TestStringToString()
+ {
+ string request = "{\"method\":\"internal.echo\",\"params\":[\"hi\"],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"hi\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+
+ Assert.Equal(result.Result, expectedResult);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ var acutalDate = DateTime.Parse(result.Result.Substring(27, 33));
+ Assert.Equal(expectedDate, acutalDate);
+ }
+
+ [Theory]
+ [InlineData(@"{""method"":""NullableFloatToNullableFloat"",""params"":[1.2345],""id"":1}", "{\"jsonrpc\":\"2.0\",\"result\":1.2345,\"id\":1}")]
+ [InlineData(@"{""method"":""NullableFloatToNullableFloat"",""params"":[3.14159],""id"":1}", "{\"jsonrpc\":\"2.0\",\"result\":3.14159,\"id\":1}")]
+ [InlineData(@"{""method"":""NullableFloatToNullableFloat"",""params"":[null],""id"":1}", "{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":1}")]
+ public void NullableFloatToNullableFloat(string request, string response)
+ {
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.Equal(response, result.Result);
+ }
+
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.Equal(result.Result, expectedResult);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.Equal(result.Result, expectedResult);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void StringToThrowingException()
+ {
+ string request = "{\"method\":\"StringToThrowingException\",\"params\":[\"some string\"],\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.Contains("-32603", result.Result);
+ }
+
+ [Fact]
+ public void StringToRefException()
+ {
+ string request = "{\"method\":\"StringToRefException\",\"params\":[\"some string\"],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"refException worked\",\"code\":-1,\"data\":null},\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.True(JToken.DeepEquals(JObject.Parse(expectedResult), JObject.Parse(result.Result)));
+ }
+
+ [Fact]
+ public void StringToThrowJsonRpcException()
+ {
+ string request = "{\"method\":\"StringToThrowJsonRpcException\",\"params\":[\"some string\"],\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.Contains("-2700", result.Result);
+ }
+
+ [Fact]
+ public void ReturnsDateTime()
+ {
+ string request = "{\"method\":\"ReturnsDateTime\",\"params\":[],\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+
+ [Fact]
+ public void IntToInt()
+ {
+ string request = "{\"method\":\"IntToInt\",\"params\":[789],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void OptionalParamInt16()
+ {
+ string request = "{\"method\":\"TestOptionalParamInt16\",\"params\":[789],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void OptionalParamInt16NoParam()
+ {
+ string request = "{\"method\":\"TestOptionalParamInt16\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void Int16ToInt16()
+ {
+ string request = "{\"method\":\"Int16ToInt16\",\"params\":[789],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void Int32ToInt32()
+ {
+ string request = "{\"method\":\"Int32ToInt32\",\"params\":[789],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":789,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void Int64ToInt64()
+ {
+ string request = "{\"method\":\"Int64ToInt64\",\"params\":[78915984515564],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":78915984515564,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+
+ [Fact]
+ public void TestOptionalParamByteMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbyteMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShortMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamintMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamint\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLongMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshortMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUintMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlongMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloatMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDoubleMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBoolMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParambool\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamCharMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimalMissing()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":[],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void TestOptionalParamBytePresent()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbytePresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShortPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamintPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamint\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLongPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshortPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUintPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlongPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloatPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDoublePresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBoolPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParambool\",\"params\":[false],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamCharPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar\",\"params\":[" + (int)'b' + "],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"b\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimalPresent()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":[71],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void TestOptionalParamBytePresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbytePresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShortPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamintPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamint\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLongPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshortPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUintPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlongPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloatPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDoublePresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBoolPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambool\",\"params\":{\"input\":false},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamCharPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar\",\"params\":{\"input\":" + (int)'c' + "},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"c\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimalPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":{\"input\":71},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":71.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void TestOptionalParamByteMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbyteMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShortMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamintMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamint\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLongMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshortMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUintMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlongMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloatMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDoubleMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBoolMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambool\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamCharMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"a\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimalMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal\",\"params\":{},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":1.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void TestOptionalParamByte_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbyte_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShort_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamint_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLong_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshort_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUint_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlong_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloat_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDouble_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBool_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamChar_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimal_2ndMissingObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":{input1:123},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void TestOptionalParamByte_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":{input1:123, input2: 67},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamByte_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":[123, 67],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":67,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamByte_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambyte_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbyte_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":{input1:123, input2: 97},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":97,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbyte_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":[123, 98],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":98,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamSbyte_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamsbyte_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":126,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShort_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShort_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamShort_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamshort_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamint_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamint_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamint_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamint_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLong_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLong_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamLong_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamlong_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshort_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshort_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUshort_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamushort_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUint_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUint_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUint_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamuint_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlong_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlong_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamUlong_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamulong_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloat_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloat_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamFloat_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamfloat_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDouble_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDouble_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDouble_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdouble_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBool_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBool_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":[true, false],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamBool_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParambool_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamChar_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":{\"input1\":" + (int)'c' + ", \"input2\":" + (int)'d' + "},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamChar_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":[" + (int)'c' + ", " + (int)'d' + "],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamChar_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamchar_2x\",\"params\":[" + (int)'c' + "],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":\"d\",\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimal_2ndPresentObjectSyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":{input1:123, input2: 671},\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimal_2ndPresentArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":[123, 671],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":671.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+ [Fact]
+ public void TestOptionalParamDecimal_2ndMissingArraySyntax()
+ {
+ string request = "{\"method\":\"TestOptionalParamdecimal_2x\",\"params\":[123],\"id\":1}";
+ string expectedResult = "{\"jsonrpc\":\"2.0\",\"result\":987.0,\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.DoesNotContain("error", result.Result);
+ Assert.Equal(expectedResult, result.Result);
+ }
+
+ [Fact]
+ public void TestBatchResultWrongRequests()
+ {
+ string request = "[{},{\"jsonrpc\":\"2.0\",\"id\":4}]";
+
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+
+ Assert.True(Regex.IsMatch(result.Result, @"\[(\{.*""error"":.*?,""id"":.*?\}),(\{.*""error"":.*?,""id"":.*?\})\]"), "Should have two errors.");
+ }
+
+ [Fact]
+ public void TestBatchResultMultipleMethodCallsNotificationAtLast()
+ {
+ string request =
+ @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""Notify"",""params"":[""Hello World!""]}]";
+
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+
+ Assert.False(result.Result.EndsWith(@",]"), "result.Result.EndsWith(@\",]\")");
+
+ }
+
+ [Fact]
+ public void TestEmptyBatchResult()
+ {
+ var secondrequest = "{\"jsonrpc\":\"2.0\",\"method\":\"Notify\",\"params\":[\"Hello World!\"]}";
+ var result = JsonRpcProcessor.ProcessAsync(secondrequest);
+ result.Wait();
+
+ Assert.True(string.IsNullOrEmpty(result.Result));
+ }
+
+
+ [Fact]
+ public void TestNotificationVoidResult()
+ {
+ var secondrequest = "{\"jsonrpc\":\"2.0\",\"method\":\"Notify\",\"params\":[\"Hello World!\"], \"id\":73}";
+ var result = JsonRpcProcessor.ProcessAsync(secondrequest);
+ result.Wait();
+ Console.WriteLine(result.Result);
+ Assert.True(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.");
+ }
+
+ [Fact]
+ public void TestLeftOutParams()
+ {
+ var request =
+ @"{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""id"":1}";
+
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+
+ Assert.False(result.Result.Contains(@"error"":{""code"":-32602"), @"According to JSON-RPC 2.0 the ""params"" member MAY be omitted.");
+ }
+
+ [Fact]
+ public void TestMultipleResults()
+ {
+ var result =
+ JsonRpcProcessor.ProcessAsync(
+ @"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1},{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]");
+ result.Wait();
+
+ Assert.EndsWith("]", result.Result);
+ }
+
+ [Fact]
+ public void TestSingleResultBatch()
+ {
+ var result =
+ JsonRpcProcessor.ProcessAsync(@"[{""jsonrpc"":""2.0"",""method"":""ReturnsDateTime"",""params"":{},""id"":1}]");
+ result.Wait();
+ Assert.False(result.Result.EndsWith("]"));
+ }
+
+ class PreProcessHandlerLocal
+ {
+ public IJsonRequest rpc = null;
+ public object context = null;
+ public int run = 0;
+
+ public IJsonRpcException PreProcess(IJsonRequest rpc, object context)
+ {
+ run++;
+
+ this.rpc = rpc;
+ this.context = context;
+
+ return null;
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.context);
+ } finally {
+ Config.SetPreProcessHandler(null);
+ }
+
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.Contains("-32603", result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(sessionId, request);
+ result.Wait();
+
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult);
+ Assert.True(JToken.DeepEquals(expected1, actual1));
+ Assert.Equal(1, preHandler.run);
+
+ h.Destroy();
+
+ var result2 = JsonRpcProcessor.ProcessAsync(sessionId, request);
+ result2.Wait();
+
+ Assert.Equal(1, preHandler.run);
+ Assert.True(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result)));
+ }
+
+ class PostProcessHandlerLocal
+ {
+ public IJsonRequest rpc = null;
+ public InvokeResult response;
+ public object context = null;
+ public int run = 0;
+ private bool changeResponse_;
+
+ public PostProcessHandlerLocal(bool changeResponse)
+ {
+ changeResponse_ = changeResponse;
+ }
+
+ public IJsonRpcException PostProcess(IJsonRequest rpc,ref InvokeResult response, object context)
+ {
+ run++;
+
+ this.rpc = rpc;
+ this.response = response;
+ this.context = context;
+
+ if (changeResponse_)
+ {
+ return new JsonRpc.Newtonsoft.JsonRpcException(-123, "Test error", null);
+ }
+ return null;
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.NotNull(handler.response);
+ Assert.Equal("Success!", (string)handler.response.SerializedResult);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.response.SerializedResult);
+ Assert.NotNull(handler.response.SerializedError);
+ Assert.Contains("-27000", handler.response.SerializedError);
+ Assert.Contains("Just some testing", handler.response.SerializedError);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.Contains("-32603", result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.response.SerializedResult);
+ Assert.NotNull(handler.response.SerializedError);
+ Assert.Contains("-32603", handler.response.SerializedError);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPreProcessHandler(null);
+ }
+ }
+
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.NotNull(handler.response);
+ Assert.Equal("Success!", (string)handler.response.SerializedResult);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.NotNull(handler.response);
+ Assert.Null(handler.response.SerializedResult);
+ Assert.NotNull(handler.response.SerializedError);
+ Assert.Contains("-27000", handler.response.SerializedError);
+ Assert.Contains("Just some testing", handler.response.SerializedError);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ AssertJsonAreEqual(expectedResult, result.Result);
+ Assert.Equal(1, handler.run);
+ Assert.NotNull(handler.rpc);
+ Assert.Null(handler.response.SerializedResult);
+ Assert.NotNull(handler.response.SerializedError);
+ Assert.Contains("-32603", handler.response.SerializedError);
+ Assert.Null(handler.context);
+ }
+ finally
+ {
+ Config.SetPostProcessHandler(null);
+ }
+ }
+
+ [Fact]
+ 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.ProcessAsync(sessionId, request);
+ result.Wait();
+
+ var actual1 = JObject.Parse(result.Result);
+ var expected1 = JObject.Parse(expectedResult);
+ Assert.True(JToken.DeepEquals(expected1, actual1));
+ Assert.Equal(1, postHandler.run);
+
+ h.Destroy();
+
+ var result2 = JsonRpcProcessor.ProcessAsync(sessionId, request);
+ result2.Wait();
+
+ Assert.Equal(1, postHandler.run);
+ Assert.True(JToken.DeepEquals(JObject.Parse(expectedResultAfterDestroy), JObject.Parse(result2.Result)));
+ }
+
+ [Fact]
+ public void TestExtraParameters()
+ {
+ string request = "{\"method\":\"ReturnsDateTime\",\"params\":{extra:\"mytext\"},\"id\":1}";
+ var result = JsonRpcProcessor.ProcessAsync(request);
+ result.Wait();
+ Assert.Contains("error", result.Result);
+ Assert.Contains("\"code\":-32602", result.Result);
+ }
+
+ [Fact]
+ public void TestCustomParameterName()
+ {
+ string 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.ProcessAsync(request("myCustomParameter"));
+ result.Wait();
+ Assert.Equal(JObject.Parse(expectedResult), JObject.Parse(result.Result));
+ // Check method can\"t be used with its actual parameter name
+ result = JsonRpcProcessor.ProcessAsync(request("arg"));
+ result.Wait();
+ Assert.Contains("-32602", result.Result); // check for \"invalid params\" error code
+ }
+
+ [Fact]
+ public void TestCustomParameterWithNoSpecificName()
+ {
+ string 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.ProcessAsync(request("arg"));
+ result.Wait();
+ Assert.Equal(JObject.Parse(expectedResult), JObject.Parse(result.Result));
+ }
+
+ [Fact]
+ 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.ProcessAsync(request);
+ result.Wait();
+ Assert.Equal(expected, result.Result);
+ }
+
+ 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.Equal(expectedJson.GetType(), actualJson.GetType());
+ 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.Equal(expectedJson.Count, actualJson.Count);
+ for (var expectedElementsEnumerator = expectedJson.GetEnumerator(); expectedElementsEnumerator.MoveNext(); )
+ {
+ Assert.True(actualJson.TryGetValue(expectedElementsEnumerator.Current.Key, out JToken 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.Equal(expectedJson.Count, actualJson.Count);
+ 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.Equal(expectedJson.Type, actualJson.Type);
+ switch (expectedJson.Type)
+ {
+ case JTokenType.Boolean:
+ Assert.Equal((bool)expectedJson.Value, (bool)actualJson.Value);
+ break;
+ case JTokenType.Integer:
+ Assert.Equal((System.Int64)expectedJson.Value, (System.Int64)actualJson.Value);
+ break;
+ case JTokenType.String:
+ Assert.Equal((string)expectedJson.Value, (string)actualJson.Value);
+ 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.JsonRpcTestN.Core/jsmn.cs b/AustinHarris.JsonRpcTestN.Core/jsmn.cs
new file mode 100644
index 0000000..14cfa91
--- /dev/null
+++ b/AustinHarris.JsonRpcTestN.Core/jsmn.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using AustinHarris.JsonRpc.Jsmn;
+using Xunit;
+
+namespace AustinHarris.JsonRpcTestN.Jsmn
+{
+ public class Test
+ {
+ [Fact]
+ public void SmallParseWorks()
+ {
+ var input = "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}";
+ var tokens = new jsmntok_t[100];
+ var success = AustinHarris.JsonRpc.Jsmn.jsmn.parse(input,tokens) > 0;
+ Assert.True(success);
+ }
+
+ [Fact]
+ public void CanGetMethod()
+ {
+ var json = "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}";
+ string value;
+ Assert.True((jsmn.parseFirstField(json, "method", out value)));
+ Assert.Equal("Add",value);
+ }
+
+ [Fact]
+ public void CanGetParamsArrayPrimitives1()
+ {
+ var json = "{\"method\":\"Add\",\"params\":[1],\"id\":1}";
+ var functionParameters = new ValueTuple();
+ string rawId = string.Empty;
+ var info = new KeyValuePair[] {new KeyValuePair("p1", typeof(int))};
+ jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info);
+ Assert.Equal(functionParameters.Item1, 1);
+ Assert.Equal(rawId, "1");
+ }
+
+ [Fact]
+ public void CanGetParamsArrayPrimitives2()
+ {
+ var json = "{\"method\":\"Add\",\"params\":[1,2],\"id\":3}";
+ var functionParameters = new ValueTuple();
+ string rawId = string.Empty;
+ var info = new KeyValuePair[] {new KeyValuePair("p1", typeof(int))};
+ jsmn.DeserializeJsonRef(json,ref functionParameters, ref rawId, info);
+ Assert.Equal(functionParameters.Item1, 1);
+ Assert.Equal(functionParameters.Item2, 2);
+ Assert.Equal(rawId, "3");
+ }
+
+ [Fact]
+ public void CanGetParamsArrayPrimitives1Nullable()
+ {
+ var json = "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}";
+ var functionParameters = new ValueTuple();
+ string rawId = string.Empty;
+ var info = new KeyValuePair[] { new KeyValuePair("p1", typeof(float?)) };
+ jsmn.DeserializeJsonRef(json, ref functionParameters, ref rawId, info);
+ Assert.Equal(functionParameters.Item1, (float?)(1.23));
+ Assert.Equal(rawId, "3");
+ }
+ }
+}
\ No newline at end of file
diff --git a/AustinHarris.JsonRpcTestN.Core/service.cs b/AustinHarris.JsonRpcTestN.Core/service.cs
new file mode 100644
index 0000000..7111559
--- /dev/null
+++ b/AustinHarris.JsonRpcTestN.Core/service.cs
@@ -0,0 +1,394 @@
+using AustinHarris.JsonRpc;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+
+namespace AustinHarris.JsonRpcTestN
+{
+ public class TreeNode
+ {
+ public int NodeId { get; set; }
+
+ public IList Leafs { get; set; }
+ }
+
+ public class CalculatorService : JsonRpcService
+ {
+ [JsonRpcMethod]
+ private double Add(double l, double r)
+ {
+ return l + r;
+ }
+
+ [JsonRpcMethod]
+ public DateTime? NullableDateTimeToNullableDateTime(DateTime? dt)
+ {
+ return dt;
+ }
+
+ [JsonRpcMethod]
+ public float? NullableFloatToNullableFloat(float? a)
+ {
+ return a;
+ }
+
+ [JsonRpcMethod]
+ public decimal? DecimalToNullableDecimal(decimal x)
+ {
+ return x;
+ }
+
+ [JsonRpcMethod]
+ private List StringToListOfString(string input)
+ {
+ return new List() { "one", "two", "three", input };
+ }
+
+ [JsonRpcMethod]
+ private List StringToThrowingException(string input)
+ {
+ throw new Exception("Throwing Exception");
+ }
+
+ public class CustomString
+ {
+ public string str;
+ }
+
+ [JsonRpcMethod]
+ private List CustomStringToListOfString(CustomString input)
+ {
+ return new List() { "one", "two", "three", input.str };
+ }
+
+
+
+ [JsonRpcMethod("internal.echo")]
+ private string Handle_Echo(string s)
+ {
+ return s;
+ }
+
+ [JsonRpcMethod("error1")]
+ private string DevideByZero(string s)
+ {
+ var i = 0;
+ var j = 15;
+ 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 JsonRpc.Newtonsoft.JsonRpcException refException)
+ //{
+ // refException = new JsonRpc.Newtonsoft.JsonRpcException(-1, "refException worked", null);
+ // return s;
+ //}
+ [JsonRpcMethod]
+ private string StringToThrowJsonRpcException(string s)
+ {
+ throw new JsonRpc.Newtonsoft.JsonRpcException(-27000, "Just some testing", null);
+ return s;
+ }
+
+ //[JsonRpcMethod]
+ //private DateTime ReturnsDateTime()
+ //{
+ // return DateTime.Now;
+ //}
+
+ //[JsonRpcMethod]
+ //private recursiveClass ReturnsCustomRecursiveClass()
+ //{
+ // var obj = new recursiveClass() { Value1 = 10, Nested1 = new recursiveClass() { Value1 = 5 } };
+ // //obj.Nested1.Nested1 = obj;
+ // return obj;
+ //}
+
+ [JsonRpcMethod]
+ private float FloatToFloat(float input)
+ {
+ return input;
+ }
+
+ [JsonRpcMethod]
+ private double DoubleToDouble(double input)
+ {
+ return input;
+ }
+
+
+
+ [JsonRpcMethod]
+ private int IntToInt(int input)
+ {
+ return input;
+ }
+
+ [JsonRpcMethod]
+ private Int32 Int32ToInt32(Int32 input)
+ {
+ return input;
+ }
+
+ [JsonRpcMethod]
+ private Int16 Int16ToInt16(Int16 input)
+ {
+ return input;
+ }
+
+ [JsonRpcMethod]
+ private Int16 TestOptionalParamInt16(Int16 input = 789)
+ {
+ return input;
+ }
+
+ [JsonRpcMethod]
+ private Int64 Int64ToInt64(Int64 input)
+ {
+ return input;
+ }
+
+ private class RecursiveClass
+ {
+ public RecursiveClass Nested1 { get; set; }
+ public int Value1 { get; set; }
+ }
+
+ #region OptionalParams Tests
+ [JsonRpcMethod]
+ private byte TestOptionalParambyte(byte input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private sbyte TestOptionalParamsbyte(sbyte input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private short TestOptionalParamshort(short input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private int TestOptionalParamint(int input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private long TestOptionalParamlong(long input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private ushort TestOptionalParamushort(ushort input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private uint TestOptionalParamuint(uint input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private ulong TestOptionalParamulong(ulong input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private float TestOptionalParamfloat(float input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private double TestOptionalParamdouble(double input = 1)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private bool TestOptionalParambool(bool input = true)
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private char TestOptionalParamchar(char input = 'a')
+ {
+ return input;
+ }
+ [JsonRpcMethod]
+ private decimal TestOptionalParamdecimal(decimal input = 1)
+ {
+ return input;
+ }
+
+ #endregion
+
+ [JsonRpcMethod]
+ public byte TestOptionalParambyte_2x(byte input1, byte input2 = 98)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public sbyte TestOptionalParamsbyte_2x(sbyte input1, sbyte input2 = 126)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public short TestOptionalParamshort_2x(short input1, short input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public int TestOptionalParamint_2x(int input1, int input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public long TestOptionalParamlong_2x(long input1, long input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public ushort TestOptionalParamushort_2x(ushort input1, ushort input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public uint TestOptionalParamuint_2x(uint input1, uint input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public ulong TestOptionalParamulong_2x(ulong input1, ulong input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public float TestOptionalParamfloat_2x(float input1, float input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public double TestOptionalParamdouble_2x(double input1, double input2 = 987)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public bool TestOptionalParambool_2x(bool input1, bool input2 = true)
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ public char TestOptionalParamchar_2x(char input1, char input2 = 'd')
+ {
+ return input2;
+ }
+ [JsonRpcMethod]
+ 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 JsonRpc.Newtonsoft.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 JsonRpc.Newtonsoft.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 JsonRpc.Newtonsoft.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 JsonRpc.Newtonsoft.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()}
+ // }
+ // };
+ //}
+
+ }
+}
diff --git a/TestServer_Console.Core/Program.cs b/TestServer_Console.Core/Program.cs
new file mode 100644
index 0000000..aa88d0a
--- /dev/null
+++ b/TestServer_Console.Core/Program.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using AustinHarris.JsonRpc;
+using System.Threading;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using AustinHarris.JsonRpc.Newtonsoft;
+
+namespace TestServer_Console
+{
+ class Program
+ {
+ static object[] services = new object[] {
+ new CalculatorService()
+ };
+
+ static void Main(string[] args)
+ {
+ PrintOptions();
+ for (string line = Console.ReadLine(); line != "q"; line = Console.ReadLine())
+ {
+ if (string.IsNullOrWhiteSpace(line))
+ Benchmark();
+ else if (line.StartsWith("c", StringComparison.CurrentCultureIgnoreCase))
+ ConsoleInput();
+ PrintOptions();
+ }
+ }
+
+ private static void PrintOptions()
+ {
+ Console.WriteLine("Hit Enter to run benchmark");
+ Console.WriteLine("'c' to start reading console input");
+ Console.WriteLine("'q' to quit");
+ }
+
+ private static void ConsoleInput()
+ {
+ for (string line = Console.ReadLine(); !string.IsNullOrEmpty(line); line = Console.ReadLine())
+ {
+ JsonRpcProcessor.ProcessAsync(line).ContinueWith(response => Console.WriteLine( response.Result ));
+ }
+ }
+
+ private static volatile int ctr;
+
+ private static string payload1 = "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}";
+ private static string payload2 = "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}";
+ private static string payload3 = "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}";
+ private static string payload4 = "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}";
+ private static string payload5 = "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}";
+
+ private static void Benchmark()
+ {
+ Console.WriteLine("Starting benchmark");
+ AustinHarris.JsonRpc.Config.ConfigureFactory(new AustinHarris.JsonRpc.Newtonsoft.ObjectFactory());
+ //AustinHarris.JsonRpc.Config.ConfigureFactory(new AustinHarris.JsonRpc.Jsmn.ObjectFactory());
+ var cnt = 50;
+ var iterations = 8;
+ for (int iteration = 1; iteration <= iterations; iteration++)
+ {
+ cnt *= iteration;
+ ctr = 0;
+ var handler = Handler.GetSessionHandler();
+ Task[] tasks = new Task[cnt];
+ string[] results = new string[cnt];
+ var sessionid = Handler.DefaultSessionId();
+
+// GC.Collect();
+// var sw = Stopwatch.StartNew();
+// for (int i = 0; i < cnt; i += 5)
+// {
+// tasks[i] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"Add\",\"params\":[1,2],\"id\":1}");
+// tasks[i + 1] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"AddInt\",\"params\":[1,7],\"id\":2}");
+// tasks[i + 2] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"NullableFloatToNullableFloat\",\"params\":[1.23],\"id\":3}");
+// tasks[i + 3] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"Test2\",\"params\":[3.456],\"id\":4}");
+// tasks[i + 4] = JsonRpcProcessor.ProcessAsync(handler, "{\"method\":\"StringMe\",\"params\":[\"Foo\"],\"id\":5}");
+// }
+// Task.WaitAll(tasks);
+// sw.Stop();
+// Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds);
+//
+// for (int i = 0; i < tasks.Length; i++)
+// {
+// tasks[i] = null;
+// }
+// GC.Collect();
+
+ var sw = Stopwatch.StartNew();
+ for (int i = 0; i < cnt; i+=5)
+ {
+ tasks[i] = JsonRpcProcessor.ProcessAsync2(handler, payload1);
+ tasks[i + 1] = JsonRpcProcessor.ProcessAsync2(handler, payload2);
+ tasks[i + 2] = JsonRpcProcessor.ProcessAsync2(handler, payload3);
+ tasks[i + 3] = JsonRpcProcessor.ProcessAsync2(handler, payload4);
+ tasks[i + 4] = JsonRpcProcessor.ProcessAsync2(handler, payload5);
+ }
+ Task.WaitAll(tasks);
+ sw.Stop();
+ Console.WriteLine("Async processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds);
+
+ GC.Collect();
+ sw = Stopwatch.StartNew();
+ for (int i = 0; i < cnt; i += 5)
+ {
+ results[i] = JsonRpcProcessor.Process(handler, payload1, null);
+ results[i + 1] = JsonRpcProcessor.Process(handler, payload2, null);
+ results[i + 2] = JsonRpcProcessor.Process(handler, payload3, null);
+ results[i + 3] = JsonRpcProcessor.Process(handler, payload4, null);
+ results[i + 4] = JsonRpcProcessor.Process(handler, payload5, null);
+ }
+ sw.Stop();
+ Console.WriteLine("Direct processed {0} rpc in {1}ms for {2} rpc/sec", cnt, sw.ElapsedMilliseconds, (double)cnt * 1000d / sw.ElapsedMilliseconds);
+ }
+
+
+ Console.WriteLine("Finished benchmark...");
+ }
+
+ }
+
+
+}
diff --git a/TestServer_Console.Core/TestServer_Console.Core.csproj b/TestServer_Console.Core/TestServer_Console.Core.csproj
new file mode 100644
index 0000000..1a70e75
--- /dev/null
+++ b/TestServer_Console.Core/TestServer_Console.Core.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ netcoreapp3.0
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestServer_Console.Core/service.cs b/TestServer_Console.Core/service.cs
new file mode 100644
index 0000000..0b99c50
--- /dev/null
+++ b/TestServer_Console.Core/service.cs
@@ -0,0 +1,131 @@
+using AustinHarris.JsonRpc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TestServer_Console
+{
+ public class CalculatorService : JsonRpcService
+ {
+ [JsonRpcMethod]
+ 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)
+ {
+ return a;
+ }
+
+ [JsonRpcMethod]
+ public decimal? Test2(decimal x)
+ {
+ 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;
+ }
+ }
+}