I'm trying to send a POST request to the Livecoin API. I have ensured that every parameter and the encoding is correct, but I keep getting a weird response:
{"success":false,"exception": "Unknown currency pair [currencyPair={1}]|null"}
This is what I'm trying to post:
string response = PrivatePostQuery("exchange/buymarket", "currencyPair=BTC/USD&price=12&amount=12");
And this is the method:
public string PrivatePostQuery(string requestUrl, string parameters = "")
{
parameters = http_build_query(parameters);
string Sign = HashHMAC(this.Exchange.ExchangeConnection.ApiSecretKey, parameters).ToUpper();
string uri = this.Exchange.ExchangeConnection.ApiUrl + requestUrl + "?" + parameters;
byte[] bytes = Encoding.UTF8.GetBytes(parameters);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = bytes.Length;
request.Headers["Api-Key"] = this.Exchange.ExchangeConnection.ApiKey;
request.Headers["Sign"] = Sign;
Stream dataStream = request.GetRequestStream();
dataStream.Write(bytes, 0, bytes.Length);
try
{
WebResponse WebResponse = request.GetResponse();
dataStream = WebResponse.GetResponseStream();
StreamReader StreamReader = new StreamReader(dataStream);
return StreamReader.ReadToEnd();
}
catch (WebException ex)
{
return new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
}
}
I have succeeded getting tickers and my balance from the API, so the problem is not because of the signature or headers.
I have tried changing the request to upper / lower case, and adding the parameters as request headers, with and without them in URL.
Thanks for the help!
Ok so there was no problem at all, LiveCoin exchange doesn't work with BTC-USDT pair, only with BTC-USD. So the response was correct, even tough it was a bit messy.
I have an application that creates Survey Monkey collectors for a survey using the 'create_collector' API method. That works perfectly. The problem is that it always creates collectors with the 'Multiple Responses' set to false. I need collectors created through the API to have 'Multiple Responses' set to true. There doesn't seem to be any option in the API call to specify that.
How can I set 'Multiple Responses' to true using the 'create_collector' API?
Here is my code in c#:
class CollectorJSON
{
public string type { get; set; }
public string name { get; set; }
}
private string CreateCollectorURL = "https://api.surveymonkey.net/v2/collectors/create_collector?api_key={API_KEY_VALUE}";
public CollectorResponseJSONWrapper CreateCollector(string APIKey, string AccessToken, long SurveyId, string CollectorName)
{
_LastException = null;
CollectorResponseJSONWrapper collectorRv = new CollectorResponseJSONWrapper();
collectorRv.status = -1;
try
{
string url = CreateCollectorURL.Replace("{API_KEY_VALUE}", APIKey);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.Headers.Add("Authorization", "bearer " + AccessToken);
CollectorJSON collector = new CollectorJSON()
{
type = "weblink",
name = CollectorName
};
CollectorJSONWrapper wrapper = new CollectorJSONWrapper()
{
survey_id = SurveyId.ToString(),
collector = collector
};
string JSONData = JsonConvert.SerializeObject(wrapper);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytes = encoding.GetBytes(JSONData);
request.ContentType = "application/json";
request.ContentLength = bytes.Length;
Stream rstream = request.GetRequestStream();
rstream.Write(bytes, 0, bytes.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string responseBody = string.Empty;
using (var reader = new StreamReader(response.GetResponseStream(), ASCIIEncoding.ASCII))
{
responseBody = reader.ReadToEnd();
}
collectorRv = JsonConvert.DeserializeObject<CollectorResponseJSONWrapper>(responseBody);
}
catch( Exception ex )
{
_LastException = ex;
}
return collectorRv;
}
Thanks,
This was not supported in API v2 but can now be done using API v3, https://developer.surveymonkey.com/api/v3/#surveys-id-collectors
By setting the field allow_multiple_responses when doing a POST to /surveys/{id}/collectors to create a new collector.
I am writing an MVC Web API the make async HttpWebRequest calls. I am getting 2 different exceptions. Below is the method I am using.
The 1st exception is: "This stream does not support seek operations." and it is happening on the responseStream.
The 2nd exception is: "timeouts are not supported on this stream" and that is happening on the MemoryStream content.
What am I doing wrong? I have been Googling but not really finding any solution.
Thanks,
Rhonda
private async Task GetHtmlContentAsync(string requestUri, string userAgent, string referrer, bool keepAlive, TimeSpan timeout, bool forceTimeoutWhileReading, string proxy, string requestMethod, string type)
{
//string to hold Response
string output = null;
//create request object
var request = (HttpWebRequest)WebRequest.Create(requestUri);
var content = new MemoryStream();
request.Method = requestMethod;
request.KeepAlive = keepAlive;
request.Headers.Set("Pragma", "no-cache");
request.Timeout = (Int32)timeout.TotalMilliseconds;
request.ReadWriteTimeout = (Int32)timeout.TotalMilliseconds;
request.Referer = referrer;
request.Proxy = new WebProxy(proxy);
request.UserAgent = userAgent;
try
{
using (WebResponse response = await request.GetResponseAsync().ConfigureAwait(false))
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
await responseStream.CopyToAsync(content);
}
}
var sr = new StreamReader(content);
output = sr.ReadToEnd();
sr.Close();
}
}
catch (Exception ex)
{
output = string.Empty;
var message = ("The API caused an exception in the " + type + ".\r\n " + requestUri + "\r\n" + ex);
Logger.Write(message);
}
return output;
}
I fixed the issue by adding
content.Position = 0
before new StreamReader line. Now I just need to get it work with GZip compression.
Rhonda
I just code 4 methods for API REST, but the last I need is not working. This is deleting the message queue. I have this code:
public static string DeleteMessage(String queueName, string account, byte[] key, string endpoint, string popreceipt,string messageid)
{
string requestMethod = "DELETE";
String urlPath = String.Format("{0}/messages/{1}?popreceipt={2}", queueName,Uri.EscapeDataString(messageid),Uri.EscapeDataString(popreceipt));
String storageServiceVersion = "2009-09-19";
String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = String.Format(
"x-ms-date:{0}\nx-ms-version:{1}",
dateInRfc1123Format,
storageServiceVersion);
String canonicalizedResource = String.Format("/{0}/{1}", account, urlPath);
//String canonicalizedResource = String.Format("/{0}/{1}\npopreceipt:{2}", account, urlPath, popreceipt);
String stringToSign = String.Format(
"{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}",
requestMethod,
canonicalizedHeaders,
canonicalizedResource);
String authorizationHeader = CreateAuthorizationHeader(stringToSign, account, key);
Uri uri = new Uri(endpoint + urlPath);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = requestMethod;
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", storageServiceVersion);
request.Headers.Add("Authorization", authorizationHeader);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream dataStream = response.GetResponseStream();
return response.StatusCode.ToString();
}
}
public static string GetMessage(String queueName,string account, byte[] key,string endpoint)
{
string requestMethod = "GET";
String urlPath = String.Format("{0}/messages", queueName);
String storageServiceVersion = "2009-09-19";
String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = String.Format(
"x-ms-date:{0}\nx-ms-version:{1}",
dateInRfc1123Format,
storageServiceVersion );
String canonicalizedResource = String.Format("/{0}/{1}", account, urlPath);
String stringToSign = String.Format(
"{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}",
requestMethod,
canonicalizedHeaders,
canonicalizedResource);
String authorizationHeader = CreateAuthorizationHeader(stringToSign,account,key);
Uri uri = new Uri(endpoint + urlPath);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = requestMethod;
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", storageServiceVersion );
request.Headers.Add("Authorization", authorizationHeader);
request.Accept = "application/atom+xml,application/xml";
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream dataStream = response.GetResponseStream();
using (StreamReader reader = new StreamReader(dataStream))
{
String responseFromServer = reader.ReadToEnd();
return responseFromServer;
}
}
}
GetMessage is just working and DeleteMessage is not working, the CreateAuthorithation Headers Code is :
private static String CreateAuthorizationHeader(String canonicalizedString, string account, byte[] key)
{
String signature = string.Empty;
using (HMACSHA256 hmacSha256 = new HMACSHA256(key))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
account,
signature);
return authorizationHeader;
}
I pass the KEY using "Convert.FromBase64String(AccountSharedKey)", that works for GetMessage (and also another method for put message), but this is not working for DELETING THE MESSAGE.
I see the API in MSDN and DELETE and GET message use the same parameters, except the parameters passed by the query string.
SOLVED
The problem was that I dinĀ“t use UriEscape for the parameters in the Uri string, and sometimes the URL was valid and sometimes not.
I believe there's an issue with the way you're constructing "canonicalizedResource" string. Based on the documentation here: http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx (scroll down to the section titled "Constructing the Canonicalized Resource String"), you should not be passing the Query String parameters as part of the main canonicalized resource string. They should be appended separately.
Can you see if using the following works:
string canonicalizedResource = string.Format("/{0}/{1}/messages/{2}\npopreceipt:{3}", account, queueName, messageid, popreceipt);
Hope this helps.
I tried the following code and it worked fine for me. I created a queue, inserted a message did a "GET" message on that to get the pop receipt and then deleted the message. Only thing I modified in your code is the canonicalizedResource string based on my answer above:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.IO;
using System.Security.Cryptography;
using System.Globalization;
namespace ConsoleApplication15
{
class Program
{
static void Main(string[] args)
{
string messageId = "<message id e.g. ba9bdbe6-cd10-465d-ab32-90756ea0471d>";
string queueName = "<queue name e.g. abc>";
string accountName = "<your account name>";
string accountKey = "<you account key base64 encoded string>";
string endpoint = "http://accountname.queue.core.windows.net/";
string popreceipt = "<pop receipt e.g. AgAAAAEAAAAAAAAACuMLtGTIzQE=>";
var result = DeleteMessage(queueName, accountName, Convert.FromBase64String(accountKey), endpoint,
popreceipt, messageId);
}
public static string DeleteMessage(String queueName, string account, byte[] key, string endpoint, string popreceipt, string messageid)
{
string requestMethod = "DELETE";
String urlPath = String.Format("{0}/messages/{1}?popreceipt={2}", queueName, Uri.EscapeDataString(messageid), Uri.EscapeDataString(popreceipt));
String storageServiceVersion = "2009-09-19";
String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = String.Format(
"x-ms-date:{0}\nx-ms-version:{1}",
dateInRfc1123Format,
storageServiceVersion);
String canonicalizedResource = string.Format("/{0}/{1}/messages/{2}\npopreceipt:{3}", account, queueName, messageid, popreceipt);
String stringToSign = String.Format(
"{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}",
requestMethod,
canonicalizedHeaders,
canonicalizedResource);
String authorizationHeader = CreateAuthorizationHeader(stringToSign, account, key);
Uri uri = new Uri(endpoint + urlPath);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = requestMethod;
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", storageServiceVersion);
request.Headers.Add("Authorization", authorizationHeader);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream dataStream = response.GetResponseStream();
return response.StatusCode.ToString();
}
}
private static String CreateAuthorizationHeader(String canonicalizedString, string account, byte[] key)
{
String signature = string.Empty;
using (HMACSHA256 hmacSha256 = new HMACSHA256(key))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
account,
signature);
return authorizationHeader;
}
}
}
I have a script sending a multi part mime ie a a soap with attachments. I am using C# httpWebRequest class. I am getting an error that says the content length is required yet I am setting the content length dynamically in my code using webrequest's contentLength property. any ideas why this could be? thanx!
this is the code:
public void sendSOAPoverHttpVoda()
{
try
{
string xmlDoc = this.soapXml;
byte[] bytes;
bytes = Encoding.UTF8.GetBytes(xmlDoc);
long contentSize = bytes.Length;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(conectionUrl);
req.SendChunked = true;
CredentialCache credentialCacheObj = new CredentialCache();
credentialCacheObj.Add(
new Uri(conectionUrl),
"Basic", new NetworkCredential("dddfff", "dddddd"));
credentialCacheObj.Add(new Uri(conectionUrl), "Digest", new NetworkCredential("dddfff", "dddddd"));
req.Credentials = credentialCacheObj;
req.Method = "POST";
req.ProtocolVersion = HttpVersion.Version11;
req.ContentLength = xmlDoc.Length;
req.ContentType = "multipart/related; boundary=\"----=cellsmart_mm7_SOAP\";type=\"text/xml\";Start=\"</cellsmart_mm7_submit>\"";
req.AllowWriteStreamBuffering = true;
req.Timeout = 20000;
req.Headers.Add("SOAPAction", "");
//req.Connection = "";
if (bytes != null)
{
using (Stream outputStream = req.GetRequestStream())
{
outputStream.Write(bytes, 0, xmlDoc.Length);
}
}
using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
{
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string responseText = reader.ReadToEnd();
Console.WriteLine("Response received from URI : " + responseText);
Console.ReadLine();
}
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error : " + ex.Message + "\n" + ex.StackTrace);
Console.ReadLine();
}
}
The error/exception i get is COntent length required (411)
You can't use both SendChunked=true and ContentLength. The easiest thing to do would be to use a chunked response and omit the ContentLength. You could also retain the ContentLength and omit the SendChunked if you want though.
In case you're not familiar with it, wikipedia has a nice description of chunking.
You declare contentLength as the length of the byte[] that you send ('bytes') and then you use the length of xmlDoc as the content length - which will give a different length than actual. Then you use the same xmlDoc.Length in outputStream.Write.
Why are you not using bytes.Length in both cases? Or contentLength which you've declared but never used, I believe that is your problem, you are sending xmlDoc.Length (Length of a string) for bytes.Length (length of a byte array converted from a string), so when the file is longer than expected by the sent length, the error returns.
Try this:
public void sendSOAPoverHttpVoda()
{
try
{
string xmlDoc = this.soapXml;
byte[] bytes;
bytes = Encoding.UTF8.GetBytes(xmlDoc);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(conectionUrl);
req.SendChunked = true;
CredentialCache credentialCacheObj = new CredentialCache();
credentialCacheObj.Add(
new Uri(conectionUrl),
"Basic", new NetworkCredential("dddfff", "dddddd"));
credentialCacheObj.Add(new Uri(conectionUrl), "Digest", new NetworkCredential("dddfff", "dddddd"));
req.Credentials = credentialCacheObj;
req.Method = "POST";
req.ProtocolVersion = HttpVersion.Version11;
req.ContentLength = bytes.Length;
req.ContentType = "multipart/related; boundary=\"----=cellsmart_mm7_SOAP\";type=\"text/xml\";Start=\"</cellsmart_mm7_submit>\"";
req.AllowWriteStreamBuffering = true;
req.Timeout = 20000;
req.Headers.Add("SOAPAction", "");
//req.Connection = "";
if (bytes != null)
{
using (Stream outputStream = req.GetRequestStream())
{
outputStream.Write(bytes, 0, bytes.Length);
}
}
using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
{
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string responseText = reader.ReadToEnd();
Console.WriteLine("Response received from URI : " + responseText);
Console.ReadLine();
}
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error : " + ex.Message + "\n" + ex.StackTrace);
Console.ReadLine();
}
}