Microsoft Face Detect API code example Bad Request - azure

I have been trying to solve this bad request error. I am able to make the request call and Azure reports total calls correctly and also reports total errors.
I can not get this code example to work; however if I send this via their online console all is fine:
static async void MakeRequest()
{
string key1 = "YourKey"; // azure the one should work
string data = "https://pbs.twimg.com/profile_images/476054279438868480/vvv5YG0Q.jpeg";
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request parameters
queryString["returnFaceId"] = "true";
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key1);
Console.Beep();
var uri = "https://westus.api.cognitive.microsoft.com/face/v1.0/detect?" + queryString;
//string statusURL = HttpContext.Current.Request.Url.Host;
//console.WriteLine("Your Status URL address is :" + statusURL);
HttpResponseMessage response;
// Request body
// byte[] byteData = Encoding.UTF8.GetBytes("{url: https://pbs.twimg.com/profile_images/476054279438868480/vvv5YG0Q.jpeg}");
byte[] byteData = Encoding.UTF8.
GetBytes("{"+ "url"+":"+"https://pbs.twimg.com/profile_images/476054279438868480/vvv5YG0Q.jpeg" + "}");
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType =
new MediaTypeHeaderValue("application/json");
response = await client.PostAsync(uri, content);
}
HttpRequestMessage request =
new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StringContent("{body}",
Encoding.UTF8,
"application/json");
//CONTENT-TYPE header
await client.SendAsync(request)
.ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
Console.WriteLine("-----------------------------------");
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("End of Post return from MS");
Console.WriteLine("Hit ENTER to exit...");
Console.ReadKey();
});
}// end of Make request

Your JSON is malformed. Your fields and non-scalar fields must be quoted. You also have some unnecessary code. Here's code that works:
static async void MakeRequest()
{
string key1 = "YourKey"; // azure the one should work
string imageUri = "https://pbs.twimg.com/profile_images/476054279438868480/vvv5YG0Q.jpeg";
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request parameters
queryString["returnFaceId"] = "true";
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key1);
var uri = "https://westus.api.cognitive.microsoft.com/face/v1.0/detect?" + queryString;
string body = "{\"url\":\"" + imageUri + "\"}";
using (var content = new StringContent(body, Encoding.UTF8, "application/json"))
{
await client.PostAsync(uri, content)
.ContinueWith(async responseTask =>
{
var responseBody = await responseTask.Result.Content.ReadAsStringAsync();
Console.WriteLine("Response: {0}", responseBody);
Console.WriteLine("-----------------------------------");
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine("End of Post return from MS");
Console.WriteLine("Hit ENTER to exit...");
Console.ReadKey();
});
}
}// end of Make request
If you're using Visual Studio, I would recommend the NuGet package as this will handle much of the mundane details for you, including C# types for responses.

Related

how to pass Body for ADLS Gen-2 as a stream

I'm Using ADLS Gen2 Path-Update API to update file from ADLS which is already created.
As a body i can easily pass string which is working fine but the same with Stream is not working.
i'm reading local file data and trying to store it into stream and pass as a body but getting an error of Http request header is invalid
I have a quick test at my side, the following code which read local file as stream, then upload the stream to adls gen2. It works fine. Please try it at your side, and let me know if you have more issues.
static void Main(string[] args)
{
var auth = new AzureServiceTokenProvider();
const string url = "https://storage.azure.com/";
string token = auth.GetAccessTokenAsync(url).Result;
string requestUri = "https://xxx.dfs.core.windows.net/t11/b.txt?action=append&position=0";
var method = new HttpMethod("PATCH");
// read local file as stream
var mystream = File.OpenRead(#"D:\temp\1\test1.txt");
Console.WriteLine($"the stream length is: {mystream.Length}");
Console.WriteLine($"the position of the stream is: {mystream.Position}");
var stream_length = mystream.Length;
var request = new HttpRequestMessage(method, requestUri)
{
//Content = new StringContent(upload_string)
Content = new StreamContent(mystream)
};
// Add some defined headers
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
var i = request.Content.AsString().Length;
Console.WriteLine(request.Content.AsString());
var httpClient = new HttpClient();
var result = httpClient.SendAsync(request).Result;
Console.WriteLine("append result status code: "+ (int)result.StatusCode);
//for flush
string requestUri_2 = "https://xxx.dfs.core.windows.net/t11/b.txt?action=flush&position="+stream_length;
var request_2 = new HttpRequestMessage(method,requestUri_2);
using (HttpClient httpClient_2 = new HttpClient())
{
httpClient_2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = httpClient_2.SendAsync(request_2).Result;
Console.WriteLine("flush result status code: " + (int)response.StatusCode);
}

Issue with Updating file in ADLS Gen2 using Rest-API

I'm using ADLS Gen2 using rest api Path-Update i'm trying to update data into already created created blank file into ADLS.
but whenever i'm trying to use the API i'm getting below response from API.
{StatusCode: 202, ReasonPhrase: 'Accepted'}
but still the file will be empty.
string requestUri = "https://XXXXXXX.dfs.core.windows.net/XXXXX/abc.txt?action=append&position=0";// &retainUncommittedData=false&close=true";
dynamic method = new HttpMethod("PATCH");
dynamic request = new HttpRequestMessage(method, requestUri)
{
Content = new StringContent("\"requestBody\":\"test\"")
};`enter code here`
// Add some defined headers
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authenticationToken);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
// Add some other headers or custom headers
request.Headers.TryAddWithoutValidation("Content-Length", "0");
dynamic httpClient = new HttpClient();
dynamic result = httpClient.SendAsync(request).Result;
i expect the data should be updated in file but now i'm getting 202 Accepted as a response code but file is not updated with data
also i tried append with flush operation below is the code i'm getting 405 error
string requestUri = "https://XXXXXX.dfs.core.windows.net/XXXXX/abc.txt?action=append&position=0";// &retainUncommittedData=false&close=true";
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, requestUri)
{
Content = new StringContent("\"requestBody\":\"test\"")
};
// Add some defined headers
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authenticationToken);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
// Add some other headers or custom headers
// request.Headers.TryAddWithoutValidation("Content-Length", "0");
var httpClient = new HttpClient();
var result = httpClient.SendAsync(request).Result;
string requestUri1 = "https://XXXXX.dfs.core.windows.net/XXXXXX/abc.txt?action=flush&position=0";//&retainUncommittedData=false&close=true";
using (HttpClient httpClient1 = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authenticationToken);
HttpResponseMessage response = (httpClient.PutAsync(requestUri1, null)).Result;
}
Update:
If the files in adls gen2 is empty, you can use the method below:
static void Main(string[] args)
{
var auth = new AzureServiceTokenProvider();
const string url = "https://storage.azure.com/";
string token = auth.GetAccessTokenAsync(url).Result;
string requestUri = "https://xxx.dfs.core.windows.net/t11/c.txt?action=append&position=0";
var method = new HttpMethod("PATCH");
string upload_string = "have a nice day!";
var request = new HttpRequestMessage(method, requestUri)
{
Content = new StringContent(upload_string)
};
// Add some defined headers
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
var i = request.Content.AsString().Length;
Console.WriteLine(request.Content.AsString());
var httpClient = new HttpClient();
var result = httpClient.SendAsync(request).Result;
Console.WriteLine("append result status code: "+ (int)result.StatusCode);
//for flush
string requestUri_2 = "https://xxx.dfs.core.windows.net/t11/c.txt?action=flush&position="+upload_string.Length;
var request_2 = new HttpRequestMessage(method,requestUri_2);
using (HttpClient httpClient_2 = new HttpClient())
{
httpClient_2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = httpClient_2.SendAsync(request_2).Result;
Console.WriteLine("flush result status code: " + (int)response.StatusCode);
}
Console.ReadLine();
}
Test result as below, and I also check in azure, the data is flushed into the file.
Once you have received the 202 Accepted you can then call the action=flush and pass the position that you want the data to be flushed to. like below:
https://$STORAGE_ACCOUNT_NAME.dfs.core.windows.net/mydata/data/file1?action=flush&position=10

How to Post Image using Byte Array[] in windows phone

I'm trying to post image as byte array.
I have converted image to byte as using following code now I want to post it to server.
WriteableBitmap btmMap = new WriteableBitmap(bi);
System.Windows.Media.Imaging.Extensions.SaveJpeg(btmMap, ms, 200, 200, 0, 100);
result = ms.ToArray();
How can I now perform the POST action?
I suggest MIME multipart as content type. It is the content type best suited for byte array, if you ask me. One way to implement this:
public static async Task<string> Upload(byte[] data, string fileName, string uri)
{
HttpClient client = new HttpClient();
HttpMultipartFormDataContent content = new HttpMultipartFormDataContent("Upload----" + DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantCulture));
InMemoryRandomAccessStream contentStream = new InMemoryRandomAccessStream();
DataWriter dw = new DataWriter(contentStream);
dw.WriteBytes(data);
await dw.StoreAsync();
await dw.FlushAsync();
dw.DetachStream();
contentStream.Seek(0);
HttpStreamContent streamContent = new HttpStreamContent(contentStream);
content.Add(streamContent, "MIMEFile", fileName);
try
{
using (var message = await client.PostAsync(new Uri(uri), content))
{
if (message.StatusCode != HttpStatusCode.Ok)
{
return String.Format("ERROR ({0})",message.StatusCode);
}
var result = await message.Content.ReadAsStringAsync();
return result;
}
}
catch (Exception ex)
{
return String.Format("ERROR ({0})", ex.Message);
}
}
Try below code:
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
var imageForm = new ByteArrayContent(result, 0, result.Count());
imagenForm.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
form.Add(imagenForm, "image", "nameholder.jpg");
HttpResponseMessage response = await httpClient.PostAsync("URL_here", form);
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
httpClient.Dispose();
Hope this help's you to get idea about how to pass byte arry to POST into API call.
EDIT:
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(UserID), "UserID");
var imageForm = new ByteArrayContent(result, 0, result.Count());
imagenForm.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
form.Add(imagenForm, "image", "nameholder.jpg");
HttpResponseMessage response = await httpClient.PostAsync("URL_here", form);
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
httpClient.Dispose();

Send email using Office 365 using unified API

We are trying to use the O365 Unified API to send emails from our line-of-business apps. I use the following code to send the email. This throws a DataServiceQueryException exception "Unauthorized".
public async Task SendEmailAsUserAsync(EmailMessage message)
{
try
{
var graphClient = await _authenticationHelper.GetGraphClientAsync();
Message m = InitializeMessage(message);
await graphClient.Me.SendMailAsync(m, true);
}
catch (DataServiceQueryException dsqe)
{
_logger.Error("Could not get files: " + dsqe.InnerException.Message, dsqe);
throw;
}
}
private static Message InitializeMessage(EmailMessage message)
{
ItemBody body = new ItemBody {Content = message.Body, ContentType = BodyType.HTML};
Message m = new Message
{
Body = body,
Subject = message.Subject,
Importance = Importance.Normal,
};
//Add all the to email ids
if (message.ToRecipients != null)
foreach (Models.Messaging.EmailAddress emailAddress in message.ToRecipients)
{
m.ToRecipients.Add(new Recipient { EmailAddress = new Microsoft.Graph.EmailAddress { Address = emailAddress.Address, Name = emailAddress.Name } });
}
return m;
}
The code for _authenticationHelper.GetGraphClientAsync() is
public async Task<GraphService> GetGraphClientAsync()
{
Uri serviceRoot = new Uri(appConfig.GraphResourceUriBeta + appConfig.Tenant);
_graphClient = new GraphService(serviceRoot,
async () => await AcquireTokenAsyncForUser(appConfig.GraphResourceUri, appConfig.Tenant));
return _graphClient;
}
private async Task<string> AcquireTokenAsyncForUser(string resource, string tenantId)
{
AuthenticationResult authenticationResult = await GetAccessToken(resource, tenantId);
_accessCode = authenticationResult.AccessToken;
return _accessCode;
}
private async Task<AuthenticationResult> GetAccessToken(string resource, string tenantId)
{
string authority = appConfig.Authority;
AuthenticationContext authenticationContext = new AuthenticationContext(authority);
ClientCredential credential = new ClientCredential(appConfig.ClientId, appConfig.ClientSecret);
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
string userAccessToken = authHeader.Substring(authHeader.LastIndexOf(' ')).Trim();
UserAssertion userAssertion = new UserAssertion(userAccessToken);
var authenticationResult = await authenticationContext.AcquireTokenAsync(resource, credential, userAssertion);
return authenticationResult;
}
However if I change the SendEmailAsUserAsync method as shown below, the email is sent but an InvalidOperationException is thrown with message "The complex type 'System.Object' has no settable properties."
public async Task SendEmailAsUserAsync(EmailMessage message)
{
try
{
var graphClient = await _authenticationHelper.GetGraphClientAsync();
Message m = InitializeMessage(message);
//await graphClient.Me.SendMailAsync(m, true); //This did not work
var user = await graphClient.Me.ExecuteAsync();
await user.SendMailAsync(m, true);
}
catch (DataServiceQueryException dsqe)
{
_logger.Error("Could not get files: " + dsqe.InnerException.Message, dsqe);
throw;
}
}
Can any one point out if there is something wrong here.
Check the example project below, this has a working example (after you fill in the ClientID etc. in app.config).
Office 365 API demo applications
For sending email it uses the function below, which works if you set it up correctly. It also has a number of functions for Authenticating using Authorization Code Grant Flow.
public async Task SendMail(string to, string subject, string body)
{
var client = await this.AuthenticationHelper
.EnsureOutlookServicesClientCreatedAsync(
Office365Capabilities.Mail.ToString());
Message mail = new Message();
mail.ToRecipients.Add(new Recipient()
{
EmailAddress = new EmailAddress
{
Address = to,
}
});
mail.Subject = subject;
mail.Body = new ItemBody() { Content = body, ContentType = BodyType.HTML };
await client.Me.SendMailAsync(mail, true);
}
Actually, there is no assembly wrapper for the graph API.
Microsoft.Graph.dll is deprecrated.
So, you should to :
Deal with the REST requests : See here : http://graph.microsoft.io/docs/api-reference/v1.0/api/message_send
Generate a wrapper with Microsoft.Vipr project : see here : https://github.com/microsoft/vipr
For the authentication, ADAL works fine :)

Is it possible for a web server to make a HTTPS request to itself?

Imagine you have two applications, A & B, running on the same web server.
You want app A to call a webService on app B over SSL.
Is it possible to do that with an address like https://localhost/appsB/webService1?
How can the SSL handshake be done without a client (like a browser?)
It actually works when using this address http://localhost/appsB/webService1, only not in SSL mode.
However it works as well with HTTPS between the server and a browser when calling https://localhost/appsB/webService1.
Now, the strange thing is that it works sometimes but randomly fails when calling the webService on app B using HTTPS. Using HTTP it always works.
My tests are on IIS7.0 with a valid ssl certificate from Thawte with SSL option not required for app B.
Here is an exemple of my code :
string baseAddress = "http://localhost";
//or string baseAddress = "https://localhost";
var baseUri = new Uri(baseAddress);
//final url for appB
finalUrl = baseAddress + httpContext.Current.Request.ApplicationPath.TrimEnd('/') + "/" + url;
//Add a cookie to retrieve good contexte on appB
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseUri })
{
cookieContainer.Add(baseUri, new Cookie("ASP.NET_SessionId", HttpContext.Current.Session.SessionID));
HttpResponseMessage response = client.GetAsync(finalUrl).Result;
Dictionary<string, dynamic> sData;
if (response.IsSuccessStatusCode)
{
etc, etc..
}
All you have to do is create a https client in server A to talk to talk to itself. Below is my code. In my case, it is a client in server A that talks to a webserver interface on Server A. In this case, I am measuring my servers latency performance.
// Get Administration Server Status
public String adminServerStatus() {
uri = "https://" + "localhost" + ":" + adminserverport + "/home";
result = "grn";
adminlatency = 0;
// Build httpHeader entity
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> httpentity = new HttpEntity<String>(headers);
try {
// Build the httpClient
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
// Build httpClient template
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate template = new RestTemplate(requestFactory);
// Now go fire client status request & get latency duration
timenow = System.currentTimeMillis();
ResponseEntity<String> httpresult = template.exchange(uri, HttpMethod.GET, httpentity, String.class);
adminlatency = System.currentTimeMillis() - timenow;
HttpStatus statuscode = httpresult.getStatusCode();
if (statuscode != HttpStatus.OK) {
result = "yel";
adminlatency = 0;
}
httpClient.close();
// Error Caught
} catch (Exception e) {
result = "red";
adminlatency = 0;
}
return result;
}

Resources