The following code works fine for the most part:
public static string RequestServer(string methodName, List<string> parameters)
{
// Use the values you specified in the bitcoin server command line
string ServerIp = "http://localhost.:8332";
string UserName = "username";
string Password = "password";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(ServerIp);
webRequest.Credentials = new NetworkCredential(UserName, Password);
webRequest.ContentType = "application/json-rpc";
webRequest.Method = "POST";
string responseValue = string.Empty;
// Configure request type
JObject joe = new JObject();
joe.Add(new JProperty("jsonrpc", "1.0"));
joe.Add(new JProperty("id", "1"));
joe.Add(new JProperty("method", methodName));
JArray props = new JArray();
foreach (var parameter in parameters)
{
props.Add(parameter);
}
joe.Add(new JProperty("params", props));
// serialize JSON for request
string s = JsonConvert.SerializeObject(joe);
byte[] byteArray = Encoding.UTF8.GetBytes(s);
webRequest.ContentLength = byteArray.Length;
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
// deserialze the response
StreamReader sReader = null;
WebResponse webResponse = webRequest.GetResponse();
sReader = new StreamReader(webResponse.GetResponseStream(), true);
responseValue = sReader.ReadToEnd();
var data = JsonConvert.DeserializeObject(responseValue).ToString();
return data;
}
I can then use a methodName
such as getnewaddress
to get data back from the server:
static void Main(string[] args)
{
Console.WriteLine(RequestServer("getnewaddress", new List<string>(){"","legacy"}));
}
That will return something like this:
{
"result": "1EWJkGrirdhXpduoNdccxaCx7syqWHuDcK",
"error": null,
"id": "1"
}
The above methodName works fine when using the terminal too:
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0/bin$ ./bitcoin-cli getnewaddress "" "legacy"
1EWJkGrirdhXpduoNdccxaCx7syqWHuDcK
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$
I can use a few methodNames the same way and they work fine. However, when I use getblockhash
:
static void Main(string[] args)
{
Console.WriteLine(RequestServer("getblockhash", new List<string>(){"0"}));
}
It gives me the following error:
bitcoin@desktop:~/Code/blockchain-app$ dotnet run
Unhandled exception. System.Net.WebException: The remote server returned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
at blockchain-app.Program.RequestServer(String methodName, List`1 parameters) in /home/bitcoin/Code/blockchain-app/Program.cs:line 72
at blockchain-app.Program.Main(String[] args) in /home/bitcoin/Code/blockchain-app/Program.cs:line 29
bitcoin@desktop:~/Code/blockchain-app$
When debugging, the error happens on this line:
WebResponse webResponse = webRequest.GetResponse();
If I try to check the output manually using that methodName in the terminal such as the following, it works fine:
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$ ./bitcoin-cli getblockhash 0
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
bitcoin@desktop:~/Downloads/bitcoin-0.20.0-x86_64-linux-gnu/bitcoin-0.20.0/bin$
The request example structures look the same to me other than the methodName and the parameters sent:
https://bitcoincore.org/en/doc/0.20.0/rpc/wallet/getnewaddress/ https://bitcoincore.org/en/doc/0.20.0/rpc/blockchain/getblockhash/
Anyone know why this is happening?
I think the problem is that you are passing the wrong parameter type for the height index when calling getblockhash
. The documentation you linked to says that it should be a numeric (integer) parameter, but you are passing a string. In contrast, the getnewaddress
method uses string parameters, so your existing code works for that.
If you capture the JSON that is being generated by your RequestServer
method, it looks like this:
{"jsonrpc":"1.0","id":"1","method":"getblockhash","params":["0"]}
But the sample in the documentation for getblockhash
looks like this:
{"jsonrpc":"1.0","id":"curltest","method":"getblockhash","params":[1000]}
Notice that the value in the params
array is not quoted in the sample, whereas it is quoted in yours.
To fix, try the following:
Change the method signature for your existing RequestServer
method from this:
public static string RequestServer(string methodName, List<string> parameters)
to this:
public static string RequestServer(string methodName, List<JToken> parameters)
Create a new overload of the RequestServer
method using the old signature which calls the existing one you just changed. This will allow your other method call(s) which already work (e.g. getnewaddress
) to keep working with no changes.
public static string RequestServer(string methodName, List<string> parameters)
{
return RequestServer(methodName, parameters.Select(p => new JValue(p)).ToList<JToken>());
}
Change the code which calls getblockhash
from this:
Console.WriteLine(RequestServer("getblockhash", new List<string>() { "0" }));
to this:
Console.WriteLine(RequestServer("getblockhash", new List<JToken>() { new JValue(0) }));
Note that I answered a similar question for you back in 2018 in which I recommended the same steps 1 and 2 shown above, so you may have already done that part. If so, all you need to do is step 3.