Microsoft Cognitive Face API Person Group Create Error - azure-cognitive-services

I'm trying to create a person-group using MS Cognitive face API but I keep getting the error message "The remote server returned an error: (404) Not Found.". Below is my source code. Would be glad if anybody could help me solve this.
using (var q3 = new WebClient())
{
q3.Headers.Add(HttpRequestHeader.ContentType, "application/json");
q3.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
string url = "https://eastus.api.cognitive.microsoft.com/face/v1.0/persongroups/identificationapp2";
string json = "{\"name\":\"" + "TEST" + "\", \"userData\":\"" + "TEST INFORMATION" + "\" }";
string str = q3.UploadString(url, json);
}

If you look at the documentation for your region for this Create PersonGroup method here, you must do a PUT operation:
In your code you are doing the following:
string str = q3.UploadString(url, json);
Which is doing a POST, not a PUT (see doc here). To do a PUT, you can specify the method:
string str = q3.UploadString(url, "PUT", json);
PS: you can also use HttpClient, see why here on StackOverflow

Related

Formulating POST request to CoinSpot API

I am pulling my hair out trying to query the CoinSpot API.
The endpoint for the Read Only API is: https://www.coinspot.com.au/api/ro
The documentation states:
All requests to the API will need to include the following security
data.
Headers: key - Your API key generated from the settings page sign -
The POST data is to be signed using your secret key according to
HMAC-SHA512 method. Post Params: nonce - Any integer value which must
always be greater than the previous requests nonce value.
I try to query the 'List My Balances' endpoint via: https://www.coinspot.com.au/api/ro/my/balances
However, the code I have formulated below always returns an error: "invalid/missing nonce".
I have tried so many different variations and approaches but it is always the same error.
require(httr)
key <- "68z...39k"
secret <- "71A...48i"
result <- POST("https://www.coinspot.com.au/api/ro/my/balances",
body = list('nonce'=as.integer(as.POSIXct(Sys.time()))), add_headers("key"=key,"sign"=openssl::sha512("https://www.coinspot.com.au/api/ro/my/balances",key = secret)))
content(result)
Any help much appreciated.
Ive struggled with this too- the coinspot API guide isn't very clear.
I figured out you are meant to encode the postdata in correct json format using sha512 and add that to the sign header. See example below querying account balances on v2 of the api.
require(httr)
api_key = "68z...39k"
api_secret = "71A...48i"
base_url = "https://www.coinspot.com.au/api/v2/ro"
request = "/my/balances"
nonce = as.character(as.integer(Sys.time()))
postdata = paste0('{"nonce":"',nonce,'"}') # important to get the quotes correct
api_sign = digest::hmac(api_secret, postdata, algo="sha512",raw=F)
result = POST(paste0(base_url, request),
body = list("nonce"=nonce),
add_headers(c("key"=api_key,
"sign"=api_sign)),
encode="json"
)
cat(rawToChar(result$content))
You would change what is in postdata based on what you are doing with the API- this is a simple example to build on. If you want to see what postdata should look like prior to encryption in sign, use cat(rawToChar(result$request$options$postfields)) after making a request.
For me, I was missing the JSON string encoded postdata in the body, including the nonce. As soon as I added that, it started working.
Heres my code in c# using Restsharp and Newtonsoft
//put the nonce at the beginning
JObject joBody = JObject.Parse(#"{'nonce': '" + DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString() + "'}");
joBody.Merge(originalBody);
var client = new RestClient(_coinspotSettings.BaseURL);
RestRequest request = new RestRequest(endpoint, Method.POST);
request.AddJsonBody(JsonConvert.SerializeObject(joBody));
request.AddHeader("key", coinspotAccount.APIKey);
request.AddHeader("sign", SignData(coinspotAccount, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(joBody))).ToLower());
request.AddHeader("Content-Type", "application/json");
private string SignData(CoinspotAccount coinspotAccount, byte[] JSONData)
{
var HMAC = new HMACSHA512(Encoding.UTF8.GetBytes(coinspotAccount.APISecret));
byte[] EncodedBytes = HMAC.ComputeHash(JSONData);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i <= EncodedBytes.Length - 1; i++)
stringBuilder.Append(EncodedBytes[i].ToString("X2"));
return stringBuilder.ToString();
}

Updating Calendar Event Giving Error "The specified value is not a valid quoted string"

As of today we are getting an error when we try to update an event using Google Calendar V3 API.
Here is our code:
string certificateFile = getCertificateFile();
string certificatePassword = getCertificatePassword();
string serviceAccountEmail = getServiceAccountEmail();
X509Certificate2 certificate = new X509Certificate2(AppDomain.CurrentDomain.BaseDirectory + "certs//" + certificateFile, certificatePassword, X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { Google.Apis.Calendar.v3.CalendarService.Scope.Calendar },
User = user
}.FromCertificate(certificate));
Google.Apis.Calendar.v3.CalendarService service = new Google.Apis.Calendar.v3.CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Test",
});
try
{
Event evv = service.Events.Get(user, "6ebr4dp452m453n468movuntag").Execute();
EventsResource.UpdateRequest ur = new EventsResource.UpdateRequest(service, evv, user, evv.Id);
ur.Execute();
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
The Error message is " The specified value is not a valid quoted string. "
This is basic code that always works. We can still query and insert Events. For some reason updates have just stopped working?
Anybody else getting this?
I found what is the problem: Google API's ETag functionality seems to be broken.
To get around the issue I had to download the source code of the .NET Google API client libraries from google-api-dotnet-client Downloads and commented the call to the method AddETag() on line 189 of ClientServiceRequest.cs; that method adds the If-Match ETag header that's currently causing the issues. This file is in the GoogleApis project.
public HttpRequestMessage CreateRequest(Nullable<bool> overrideGZipEnabled = null)
{
var builder = CreateBuilder();
var request = builder.CreateRequest();
object body = GetBody();
request.SetRequestSerailizedContent(service, body, overrideGZipEnabled.HasValue
? overrideGZipEnabled.Value : service.GZipEnabled);
//AddETag(request);
return request;
}
See Protocol Reference: Updating Entries for more information on how Google API's use ETags and the If-Match header.
The problem in the Calendar API was fixed so no need to use this workaround!
Please don't use the above suggestion. Although it works, it will actually eliminate an important feature of etag in the library. A better solution is available at: https://codereview.appspot.com/96320045/
Thanks diegog for your work-around, I'm pretty sure it helped several users who were stuck today.

Not getting WeChat Follow response

I have a Debugging Official Account with WeChat. I have entered my public URL and Token into the field provided http://admin.wechat.com/debug/sandbox and also attempted debugging the request with http://admin.wechat.com/debug/
My ASP.Net [.Net4.5] Web API application's POST Method looks like the following :
public HttpResponseMessage PostMessage([FromBody]Strikemedia.Api.WeChat.TextMessage value)
{
if (value == null)
{
var richMediaMessage = new RichMediaMessage();
richMediaMessage.touser = value.FromuserName;
//Create Article
var item = new Article()
{
title = "Didn't receive anything back",
description = "Mind entering 'test'",
picurl = "URL",
url = "URL"
};
var articles = new List<Article>();
articles.Add(item);
richMediaMessage.articles = articles;
richMediaMessage.articleCount = articles.Count;
return Request.CreateResponse(HttpStatusCode.OK, richMediaMessage, "application/json");
}
var exploded = value.Content.Split(' ')[0];
var richMedia = new RichMediaMessage();
richMedia.touser = value.FromuserName;
//Create Article
var article = new Article() {
title = response.KeywordDescription,
description = response.Response,
picurl = "URL",
url = "URL"
};
var _articles = new List<Article>();
_articles.Add(article);
richMedia.articles = _articles;
richMedia.articleCount = _articles.Count;
//Return response
var resp = Request.CreateResponse(HttpStatusCode.OK, richMedia, "application/json");
//resp.RequestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return resp;
}
It needs to respond with a RichMessageType in JSON format and is received in XML format
Am i missing something or have i overlooked something?
Can you confirm that you have submitted the URL and token into admin.wechat.com and that the URL and token was accepted?
Also note you get XML and you respond with XML no json response.
Have you had a look at: http://youtu.be/kB20Zf51QWU
And then this
http://youtu.be/_2FSzD2B2F0
This is the documentation for the XML can be found when you google "wechat guide to message api"
So if you still not receiving a success message when submitting your app on admin.wechat.com then you can send me your test URL here. To find this URL check your access logs to see exactly what URL wechat is calling. Then post it here. Please note that when you hit the URL as wechat will you should only see the "echostr" printed on the screen (when viewing the source in your browser). No XML no HTML just the echostr.
Also make sure there are no spaces or newlines after or before the "echostr". When you view the source it should only be one line which is the echostr GET param's value.
The XML response only comes in later when you actually start responding to messages from users. For now Wechat is just confirming if your security is setup correctly.
Also note if your server is load balanced you will have to skip the signature validation and build your own validation when a echostr GET parameter gets passed through and only echo the "echostr" param to screen.

URI too long on post

I am making a request using the RestClient and RestRequest, after adding the parameters I get
Error:
Invalid URI: The URI string is too long.
I'm assuming this has something to do with it not posting the data correctly, Here is my code:
RestClient client = new RestClient();
client.BaseUrl = "URL";
client.Authenticator =
new HttpBasicAuthenticator("api",
"KEY");
RestRequest restRequest = new RestRequest(Method.POST);
restRequest.AddParameter("domain",
"DOMAIN", ParameterType.UrlSegment);
restRequest.Resource = "{domain}/messages";
restRequest.AddParameter("from", (string) sender["alias"] + "<email>");
restRequest.AddParameter("to", (string)recipient["alias"] + "<" + (string)recipient["email"] + ">");
restRequest.AddParameter("subject", subject);
restRequest.AddParameter("html", body);
var result = client.Execute(restRequest);
if (result.StatusCode != System.Net.HttpStatusCode.OK)
{
throw new Exception(result.ErrorMessage,new Exception(result.StatusCode + " - " + result.StatusDescription));
}
The body parameter could be very long as it is a HTML email. What causes the above error?
Here is the request that the code makes using a shorter body so that it does send
http://pastebin.com/HgbBHVpC
Full stack trace including message trying to send http://pastebin.com/dRhXire6
http://msdn.microsoft.com/en-us/library/z6c2z492.aspx
looking at the doc it says
The length of uriString exceeds 65519 characters
May be request.AddParameter(contentTyp, ContentItself, ParameterType.RequestBody);
or request.AddBody. Also try to use something like fiddler to check what the actual request (url\body) you send.
Looks like a known feature of RestSharp:
https://groups.google.com/forum/?fromgroups#!topic/restsharp/9b5bpK3gt9g

Calling a Remote Java Servlet

I have a jsp page which holds a form, it is supposed to send off the form data to a remote servlet, which calculates it, and then returns it as XML. It works, but at the moment I'm creating an instance and dispatcher which only works with local servlets whereas I want it to work with a remote servlet.
I was previously told that HTTPClient would do this, but this thing has become such a headache and it seems like a complete overkill for what I want to do. There must be some simple method as opposed to faffing around with all these jar components and dependencies?
Please give sample code if possible, I'm really a complete novice to Java, much more of a PHP guy :P
Figured it out with the help of some online resources. Had to first collect the submitted values (request.getParamater("bla")), build the data string (URLEnconder), start up a URLConnection and tell it to open a connection with the designated URL, startup an OutputStreamWriter and then tell it to add the string of data (URLEncoder), then finally read the data and print it...
Below is the gist of the code:
String postedVariable1 = request.getParameter("postedVariable1");
String postedVariable2 = request.getParameter("postedVariable2");
//Construct data here... build the string like you would with a GET URL
String data = URLEncoder.encode("postedVariable1", "UTF-8") + "=" + URLEncoder.encode(postedVariable1, "UTF-8");
data += "&" + URLEncoder.encode("postedVariable2", "UTF-8") + "=" + URLEncoder.encode(submitMethod, "UTF-8");
try {
URL calculator = new URL("http://remoteserver/Servlet");
URLConnection calcConnection = calculator.openConnection();
calcConnection.setDoOutput(true);
OutputStreamWriter outputLine = new OutputStreamWriter(calcConnection.getOutputStream());
outputLine.write(data);
outputLine.flush();
// Get the response
BufferedReader streamReader = new BufferedReader(new InputStreamReader(calcConnection.getInputStream()));
String line;
//streamReader = holding the data... can put it through a DOM loader?
while ((line = streamReader.readLine()) != null) {
PrintWriter writer = response.getWriter();
writer.print(line);
}
outputLine.close();
streamReader.close();
} catch (MalformedURLException me) {
System.out.println("MalformedURLException: " + me);
} catch (IOException ioe) {
System.out.println("IOException: " + ioe);
}

Resources