private async Task <string> HandleRequestAsync(JsonRpcRequest jsonRpcRequest, CancellationToken cancellationToken)
        {
            var methodName = jsonRpcRequest.Method;

            if (!MetadataProvider.TryGetMetadata(methodName, out var prodecureMetadata))
            {
                return(Error(JsonRpcErrorCodes.MethodNotFound, $"'{methodName}' method not found.", jsonRpcRequest.Id));
            }

            try
            {
                var methodParameters = prodecureMetadata.Parameters;
                var parameters       = new List <object>();

                if (jsonRpcRequest.Parameters is JArray jarr)
                {
                    var count = methodParameters.Count < jarr.Count ? methodParameters.Count : jarr.Count;
                    for (int i = 0; i < count; i++)
                    {
                        parameters.Add(jarr[i].ToObject(methodParameters[i].type, DefaultSerializer));
                    }
                }
                else if (jsonRpcRequest.Parameters is JObject jobj)
                {
                    for (int i = 0; i < methodParameters.Count; i++)
                    {
                        var param = methodParameters[i];
                        if (!jobj.ContainsKey(param.name))
                        {
                            return(Error(JsonRpcErrorCodes.InvalidParams,
                                         $"A value for the '{param.name}' is missing.", jsonRpcRequest.Id));
                        }
                        parameters.Add(jobj[param.name].ToObject(param.type, DefaultSerializer));
                    }
                }

                // Special case: if there is a missing parameter and the procedure is expecting a CancellationTokenSource
                // then pass the cancellationToken we have. This will allow us to cancel async requests when the server is stopped.
                if (parameters.Count == methodParameters.Count - 1)
                {
                    var position = methodParameters.FindIndex(x => x.type == typeof(CancellationToken));
                    if (position > -1)
                    {
                        parameters.Insert(position, cancellationToken);
                    }
                }
                if (parameters.Count < methodParameters.Count(x => !x.isOptional))
                {
                    return(Error(JsonRpcErrorCodes.InvalidParams,
                                 $"{methodParameters.Count} parameters were expected but {parameters.Count} were received.", jsonRpcRequest.Id));
                }

                var missingParameters = methodParameters.Count - parameters.Count;
                parameters.AddRange(methodParameters.TakeLast(missingParameters).Select(x => x.defaultValue));
                var result = prodecureMetadata.MethodInfo.Invoke(Service, parameters.ToArray());

                if (jsonRpcRequest.IsNotification)                 // the client is not interested in getting a response
                {
                    return("");
                }

                JsonRpcResponse response = null;
                if (prodecureMetadata.MethodInfo.IsAsync())
                {
                    if (!prodecureMetadata.MethodInfo.ReturnType.IsGenericType)
                    {
                        await((Task)result).ConfigureAwait(false);
                        response = JsonRpcResponse.CreateResultResponse(jsonRpcRequest.Id, null);
                    }
                    else
                    {
                        var ret = await((dynamic)result).ConfigureAwait(false);
                        response = JsonRpcResponse.CreateResultResponse(jsonRpcRequest.Id, ret);
                    }
                }
                else
                {
                    response = JsonRpcResponse.CreateResultResponse(jsonRpcRequest.Id, result);
                }
                return(response.ToJson(DefaultSettings));
            }
            catch (TargetInvocationException e)
            {
                return(Error(JsonRpcErrorCodes.InternalError, e.InnerException.Message, jsonRpcRequest.Id));
            }
            catch (Exception e)
            {
                return(Error(JsonRpcErrorCodes.InternalError, e.Message, jsonRpcRequest.Id));
            }
        }
        private string Error(JsonRpcErrorCodes code, string reason, string id)
        {
            var response = JsonRpcResponse.CreateErrorResponse(id, code, reason);

            return(id is { }