Upload image from mobile app to API with multipart/form-data - c#

I have this API where I receive an image to save it in a storage server. I've been testing the functionality in postman and works perfectly fine. But when it comes to the mobile app it does not send the image.
here you can see the Postman POST request
the code for the xamarin app is the next
var content = new MultipartFormDataContent();
var stream = File.OpenRead(_mediaFile.Path);
var streamcontent = new StreamContent(stream);
content.Add(streamcontent, "picture");
var client = new HttpClient();
HttpResponseMessage response = await cliente.PostAsync($"http://localhost:200/api/.../picture", content);
string result = response.Content.ReadAsStringAsync().Result;
Response responseData = JsonConvert.DeserializeObject<Response>(result);
if (response.IsSuccessStatusCode)
{
await Application.Current.MainPage.DisplayAlert("Correcto", "Imagen subida Correctamentel!", "OK");
_mediaFile = null;
terminado.IsEnabled = true;
}
else
{
terminado.IsEnabled = true;
await Application.Current.MainPage.DisplayAlert("Error", "Opps algo ocuirrio mal!", "OK"); }
As you can see in the postman the key picture receives the image name. I tried it also with curl and it works:
curl -X POST "http://localhost:200/api/.../picture" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "picture=#version1.jpeg;type=image/jpeg"

I've managed it to work, but using RestSharp library instead of HttpClient:
var client = new RestClient("192.168.0.2"); //the ip of your REST API
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "multipart/form-data"); // I'm using multipart form data
request.AddHeader("Authorization", "Bearer eyJ0eXAiOiJKV1QiLC"); // using JWT for auth
request.AddFile("pictureField", "/path/to/file"); //the path depends on which device you're using
IRestResponse response = client.Execute(request);
Pretty much straigt forward and works perfectly fine. Also, the "pictureField" depends on the name of the field the API requires, and the path to file should not be hardcoded. It should be given depending on where in the device the choosen image is.

Related

RestSharp Post Json Object

I am trying to Post a simple Json object using RestSharp to add a new product. I'm getting an error response from the server
"{"status":400,"error":"There was a problem in the JSON you submitted: unexpected character (after ) at line 1, column 2 [parse.c:724] in '{'product':{'name':'Product name','opt1':'Colour'}}"}"
My code:
////
var json = "{\'product\':{\'name\':\'Product name\',\'opt1\':\'Colour\'}}";
IRestClient restClient = new RestClient();
IRestRequest request = new RestRequest()
{
Resource = "https://api.targetsite.com/products/"
};
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/xml");
request.AddHeader("authorization", "Bearer " + token);
request.RequestFormat = DataFormat.Json;
request.AddJsonBody(json);
IRestResponse response = restClient.Post(request);
////
I managed to achive the result I wanted using a curl statment but I would like to do it using RestSharp.
Curl statment -
curl -X POST -H "Content-type: application/json" -H "Authorization: Bearer <ACCESS_TOKEN>"
https://api.targetsite.com/products/ -d '{"product":{"name":"Product name","opt1":"Colour"}}'
This HttpClient call also works fine
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.targetsite.com/products/"))
{
request.Headers.TryAddWithoutValidation("Authorization", "Bearer <ACCESS_TOKEN>");
request.Content = new StringContent("{\"product\":{\"name\":\"Product name\",\"opt1\":\"Colour\"}}");
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var response = await httpClient.SendAsync(request);
}
}
It looks like a limitation on the API you are calling.
When you send the json with curl, you're using different delimiters (" instead of ').
My guess is that the API you're calling doesn't properly deserialize the JSON when ' is used.
What you can try is replacing the escaped ' with " or replace this line in your code : request.AddJsonBody(json)
with
request.AddJsonBody(Newtonsoft.Json.JsonConvert.DeserializeObject(json)) provided that you have installed the newtonsoft package.

'invalid_grant' error on API call with RestSharp

I need to convert that curl request to c#. Im using RestSharp. curl request:
> curl -X POST -i https://gw.api.alphabank.eu/sandbox/auth/token \
-u "{{client_id}}:{{client_secret}}" \
-d "grant_type=client_credentials&scope=account-info-setup"
I tried the following code but I end up with 'invalid_grant' error as a response.
Any ideas what i'm doing wrong?
My code:
var client = new RestClient(url);
var request = new RestRequest();
request.Method = Method.POST;
client.Authenticator = new HttpBasicAuthenticator(ABclientID, ABclientSecret);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("scope", "account-info-setup");
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/x-www-form-urlencoded"; };
IRestResponse response = client.Execute(request);
this sample code is generated by Postman and it's working for my api which accepts application/x-www-form-urlencoded, can you add your parameters like this? Or create and make your request works on Postman and generate to C#-RestSharp it's usually works for me with minor changes.
var client = new RestClient("url");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("userId", "1234");
request.AddParameter("count", "5");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Turns out "invalid_grant" meant wrong credentials. I was giving wrong client-secret.
Request was succesfull after correcting the client_secret.

Sending HTTP post request in C# to Microsoft Bing speech API

I am trying to send a HTTP post request to microsoft Bing speech API o transcribe an audio file. First we need to send a post request to get an "access token" as a response, then this token is used (as authorisation" in another post request to upload the actual file and get the transcription in the response. I can send the first post request and successfully get the access token, but I am not able to get a reasonable response for my second post request. I follow this page: https://www.microsoft.com/cognitive-services/en-us/speech-api/documentation/api-reference-rest/bingvoicerecognition
This is the second post request:
Guid requestId = Guid.NewGuid();
var Uri = #"https://speech.platform.bing.com/recognize?version=3.0&requestid=" + requestId.ToString() + #"&appID=D4D52672-91D7-4C74-8AD8-42B1D981415A&format=json&locale=en-US&device.os=Windows%20OS&scenarios=ulm&instanceid=f1efbd27-25fd-4212-9332-77cd63176112";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, Uri);
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));
request.Headers.TryAddWithoutValidation("Content-Type", #"audio/wav; samplerate=16000");
MemoryStream ms = new MemoryStream();
using (var fs = System.IO.File.OpenRead("audio.wav"))
{
byte[] buffer = new byte[1024 * 8];
while (fs.Read(buffer, 0, buffer.Length) > 0)
{
ms.Write(buffer, 0, buffer.Length);
}
fs.Close();
}
ms.Seek(0, SeekOrigin.Begin);
HttpContent _Body = new StreamContent(ms);
request.Content = _Body;
var client2 = new HttpClient();
var response2 = client2.SendAsync(request);
I guess the problem is where I set the "Content-Type" for the header. The reason is when I debug, I don't see this property being set in the Header of the request. In fact, there is no Content-Type in the header. Any help would be appreciated. This page, which talks about the equivalent curl command, can also be helpful: https://social.msdn.microsoft.com/Forums/en-US/ad73e4f1-e576-4080-9fe7-060cc2f583ca/microsoft-bing-voice-recognition-api-authorization-404resource-not-found?forum=SpeechService
Content-Type is a content related header. The following code works for me:
public async Task<string> SendRequestAsync(string url, string bearerToken, string contentType, string fileName)
{
var content = new StreamContent(File.OpenRead(fileName));
content.Headers.TryAddWithoutValidation("Content-Type", contentType);
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
var response = await httpClient.PostAsync(url, content);
return await response.Content.ReadAsStringAsync();
}
}
The invocation in your case (if you work in synchronous context):
var result = SendRequestAsync(Uri, accessToken, "audio/wav; samplerate=16000", "audio.wav").Result;
You can send the following header instead, to not have to do 2 requests because of the token.
If you want to not have to login each time instead of using the 'Authorization': 'Bearer {TOKEN}' header you could use the 'Ocp-Apim-Subscription-Key': '{YOUR AZURE TOKEN}' in order to not have to make a authorisation factory or more requests than necessary to the application and make it faster
NOTE: {TOKEN} is a JWT token like
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzY29wZSI6Imh0dHBzOi8vc3BlZWNoLnBsYXRmb3JtLmJpbmcuY29tIiwic3Vic2NyaXB0aW9uLWlkIjoiZmFhZTNlYTkxNmI1NGMxZWEyODY4MDlhYTg3ZWE1MmUiLCJwcm9kdWN0LWlkIjoiQmluZy5TcGVlY2guUHJldmlldyIsImNvZ25pdGl2ZS1zZXJ2aWNlcy1lbmRwb2ludCI6Imh0dHBzOi8vYXBpLmNvZ25pdGl2ZS5taWNyb3NvZnQuY29tL2ludGVybmFsL3YxLjAvIiwiYXp1cmUtcmVzb3VyY2UtaWQiOiIiLCJpc3MiOiJ1cm46bXMuY29nbml0aXZlc2VydmljZXMiLCJhdWQiOiJ1cm46bXMuc3BlZWNoIiwiZXhwIjoxNTAwODgxNjIzfQ.KdlCrIJ_H0jxs1yyeyYxYR7ucbLuFKT__ep7lGJmGbU
NOTE2: {YOUR AZURE TOKEN} is like d5kals90935b40809dc6k38533c21e85 and you find it here
The request would look like this:
curl -v -X POST "https://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?language=es-ES&locale=es-ES&format=simple&requestid=req_id" -H "Ocp-Apim-Subscription-Key: d5kals90935b40809dc6k38533c21e85" -H 'Transfer-Encoding: chunked' -H 'Content-type: audio/wav; codec="audio/pcm"; samplerate=8000' --data-binary #"{BINAYFILE}.wav"

Curl request written in C# doesn't work

I'm trying to write a specific curl request in C#, and I keep getting a 500 server error response from the server. This curl request essentially makes a post request to an API by the company Highwinds. This request sends json data, and sets the Auth Bearer token header.
This is the curl request that works fine (note that I've replaced my actual bearer token with {token} and my actual account id with {accountId} to obfuscate that info):
curl -H "Authorization: Bearer {token}" -H "Content-Type: application/json" -d "#data.json" "https://striketracker.highwinds.com/api/accounts/{accountId}/purge"
Here's the C# code that gives me a generic 500 server error from the Highwinds API (note that I've replaced my actual bearer token with {token}, my actual account id with {accountId}, and the url in the json string with {url}, in order to obfuscate that personal info):
var accountId = "{accountId}";
var purgeURI = string.Format("https://striketracker.highwinds.com/api/accounts/{0}/purge", {accountId});
var query =
#"{""list"": [{""url"": ""{url}"",""recursive"": true}]}";
var token = {token};
using (var httpClient = new HttpClient())
{
var url = new Uri(purgeURI);
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url))
{
httpRequestMessage.Headers.Add(System.Net.HttpRequestHeader.Authorization.ToString(),
string.Format("Bearer {0}", token));
httpRequestMessage.Content = new StringContent(query,
Encoding.UTF8,
"application/json");
await httpClient.SendAsync(httpRequestMessage).ContinueWith(task =>
{
var response = task.Result;
var blah = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
});
}
}
Thanks!
*Update: The following line of code was added to remove the Expect header that HttpRequest adds to a request by default. After removing this header I was able to get Highwinds API to accept the request without bombing.
"request.ServicePoint.Expect100Continue = false;"
My best recommendation would be to proxy both requests through something like tcpmon http://archive.apache.org/dist/ws/tcpmon/1.0/ (Basically run the server and point to local host and have tcpmon redirect the request to striketracker.highwinds.com). Try it from curl and from your source and you should be able to see what's different between the requests.

CURL command to C# code Dropbox API

I am using Dropbox APIs to upload a file to dropbox cloud. I have the access token and I need to execute the following curl command:
curl -H "Authorization: Bearer NBNBNSBJHDKHDKJJGGD" https://api-content.dropbox.com/1/files_put/auto/ -T "C:\Tm\dd.jpg"
Could someone please let me know how to do the above in C#
Thanks for your help
Thanks for all your support. This got resolved. I feel this will be definitely useful for some one.
string filePath="C:\\Tim\\sundar.jpg";
RestClient client = new RestClient("https://api-content.dropbox.com/1/");
IRestRequest request = new RestRequest("files_put/auto/{path}", Method.PUT);
FileInfo fileInfo = new FileInfo(filePath);
long fileLength = fileInfo.Length;
request.AddHeader("Authorization", "Bearer FTXXXXXXXXXXXXXXXXXXXisqFXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
request.AddHeader("Content-Length", fileLength.ToString());
request.AddUrlSegment("path", string.Format("Public/{0}", fileInfo.Name));
byte[] data = File.ReadAllBytes(filePath);
var body = new Parameter
{
Name = "file",
Value = data,
Type = ParameterType.RequestBody,
};
request.Parameters.Add(body);
IRestResponse response = client.Execute(request);

Categories

Resources