Trustpilot OAuth Restful API: Unable to PostAsync - c#

I am trying to use the Trustpilot API, to post invitations to review products.
I have successfully gone through the authentication step as you can see in the code below, however I am unable to successfully post data to the Trustpilot Invitations API. The PostAsnyc method appears to be stuck with an WaitingForActivation status. I wonder if there is anything you can suggest to help.
Here is my code for this (the API credentials here aren't genuine!):
using (HttpClient httpClient = new HttpClient())
{
string trustPilotAccessTokenUrl = "https://api.trustpilot.com/v1/oauth/oauth-business-users-for-applications/accesstoken";
httpClient.BaseAddress = new Uri(trustPilotAccessTokenUrl);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var authString = "MyApiKey:MyApiSecret";
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Base64Encode(authString));
var stringPayload = "grant_type=password&username=MyUserEmail&password=MyPassword";
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/x-www-form-urlencoded");
HttpResponseMessage httpResponseMessage = httpClient.PostAsync(trustPilotAccessTokenUrl, httpContent).Result;
var accessTokenResponseString = httpResponseMessage.Content.ReadAsStringAsync().Result;
var accessTokenResponseObject = JsonConvert.DeserializeObject<AccessTokenResponse>(accessTokenResponseString);
// Create invitation object
var invitation = new ReviewInvitation
{
ReferenceID = "inv001",
RecipientName = "Jon Doe",
RecipientEmail = "Jon.Doe#comp.com",
Locale = "en-US"
};
var jsonInvitation = JsonConvert.SerializeObject(invitation);
var client = new HttpClient();
client.DefaultRequestHeaders.Add("token", accessTokenResponseObject.AccessToken);
var invitationsUri = new Uri("https://invitations-api.trustpilot.com/v1/private/business-units/{MyBusinessID}/invitations");
// This here as a status of WaitingForActivation!
var a = client.PostAsync(invitationsUri, new StringContent(jsonInvitation)).ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
}

This is how I solved the issue:
// Serialize our concrete class into a JSON String
var jsonInvitation = JsonConvert.SerializeObject(invitationObject);
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var stringContent = new StringContent(jsonInvitation);
// Get the access token
var token = GetAccessToken().AccessToken;
// Create a Uri
var postUri = new Uri("https://invitations-api.trustpilot.com/v1/private/business-units/{BusinessUnitID}/invitations");
// Set up the request
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, postUri);
request.Content = stringContent;
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
request.Content.Headers.Add("token", token);
// Set up the HttpClient
var httpClient = new HttpClient();
//httpClient.DefaultRequestHeaders.Accept.Clear();
//httpClient.BaseAddress = postUri;
//httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
//httpClient.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("en-US"));
var task = httpClient.SendAsync(request);
task.Wait();
This question here on SO was helpful:
How do you set the Content-Type header for an HttpClient request?

Related

How to split an HTTP Request Body in two parts?

I'm fairly new to use HTTPClient and sending REST requests to APIs, I'm currently practicing multipart upload using this Google Drive API endpoint:
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart
There's an instruction that states there to split the request body into two parts, I tried to recreate this but was unable to do so.
https://developers.google.com/drive/api/guides/manage-uploads#multipart
Here's my current code:
async void UploadFile(StorageFile fileName)
{
using (HttpClient client = new HttpClient())
{
// Opens files and convert it to stream
var resultStream = await fileName.OpenReadAsync();
var fileStreamContent = new StreamContent(resultStream.AsStream());
// Create file MetaData
var fileMetaData = JsonConvert.SerializeObject(
new { name = fileName.Name, mimetype = fileName.ContentType });
// Create POST request
var requestMessage = new HttpRequestMessage(HttpMethod.Post, uploadFileEndpoint);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
// Add request body
requestMessage.Content = new StringContent(fileMetaData, Encoding.UTF8, "application/json");
requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/related");
var response = await client.SendAsync(requestMessage);
string responseString = await response.Content.ReadAsStringAsync();
output(responseString);
}
}
Any help would be greatly appreciated, thank you!
According to the documentation on Perform a multipart upload (HTTP tab), you need the MultipartFormDataContent as suggested by #Jeremy.
There are a few things needed to perform/migrate:
Add AuthenticationHeaderValue into client.DefaultRequestHeaders.Authorization.
Create a StreamContent instance, fileStreamContent (which you have done) and specify its Headers.ContentType.
Create a StringContent instance, stringContent (which you have done).
Append both StreamContent and StringContent into the MultipartFormDataContent instance, formData.
Specify the formData's Headers.ContentType as requested in API docs.
Post the formData with await client.PostAsync(/* API Url */, formData);
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
// Opens files and convert it to stream
var resultStream = await fileName.OpenReadAsync();
var fileStreamContent = new StreamContent(resultStream.AsStream());
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(fileName.ContentType);
// Create file MetaData
var fileMetaData = JsonConvert.SerializeObject(new { name = fileName.Name, mimetype = fileName.ContentType });
var stringContent = new StringContent(fileMetaData, Encoding.UTF8, "application/json");
// Create POST request
MultipartFormDataContent formData = new MultipartFormDataContent();
formData.Add(stringContent, "metadata");
formData.Add(fileStreamContent, "media");
formData.Headers.ContentType = new MediaTypeHeaderValue("multipart/related");
var response = await client.PostAsync(uploadFileEndpoint, formData);
string responseString = await response.Content.ReadAsStringAsync();
}

ASP.NET Web API post to an external api

I would like to ask if it is possible for a created ASP.NET Web API (written in C#) to post to an external API?
If it is possible, please share sample code that can post to an url with adding headers and receive a callback from the external API.
A simple way to make HTTP-Request out of a .NET-Application is the System.Net.Http.HttpClient (MSDN). An example usage would look something like this:
// Should be a static readonly field/property, wich is only instanciated once
var client = new HttpClient();
var requestData = new Dictionary<string, string>
{
{ "field1", "Some data of the field" },
{ "field2", "Even more data" }
};
var request = new HttpRequestMessage() {
RequestUri = new Uri("https://domain.top/route"),
Method = HttpMethod.Post,
Content = new FormUrlEncodedContent(requestData)
};
request.Headers // Add or modify headers
var response = await client.SendAsync(request);
// To read the response as string
var responseString = await response.Content.ReadAsStringAsync();
// To read the response as json
var responseJson = await response.Content.ReadAsAsync<ResponseObject>();
Essentially you need use an instance of HttpClient to send an HttpRequestMessage to an endpoint.
Here is an example to post some jsonData to someEndPointUrl:
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, someEndPointUrl);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = new StringContent(jsonData, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request, CancellationToken.None);
var str = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
// handle your response
}
else
{
// or failed response ?
}

How can I Post parameter in httpClient where in postman use param

I want to post my parameter with HttpClient .
what is the Content in httpclient request body? I wrote it int the body part and when I run the project I get Error.
my code is:
string baseAddress = "https://WebServiceAddress";
Client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
HttpRequestMessage bodyRequest = new HttpRequestMessage(HttpMethod.Post, baseAddress)
bodyRequest.Content = new StringContent(JsonConvert.SerializeObject(Prescriptionrequest), Encoding.UTF8, "application/json");
var responseApi = Client.PostAsync(baseAddress, bodyRequest.Content, new System.Threading.CancellationToken(false));
what should be the format of bodyRequest.Content?
Use this code:
HttpClient client = new HttpClient();
var dictionary = new Dictionary<string, string>
{
{ "parameter0", "value0" },
{ "parameter1", "value1" }
};
var content = new FormUrlEncodedContent(dictionary);
var response = await client.PostAsync("https://WebServiceAddress", content);
var responseString = await response.Content.ReadAsStringAsync();

How to call Rest API with Content and Headers in c#?

I am trying to call Rest API with content and headers in c#. Actually I am trying to convert to c# from Python code which is:
import requests
url = 'http://url.../token'
payload = 'grant_type=password&username=username&password=password'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.request('POST', url, headers = headers, data = payload, allow_redirects=False)
print(response.text)
So far I am trying with:
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(Url);
var tmp = new HttpRequestMessage
{
Method = HttpMethod.Post,
Content =
{
}
};
var result = client.PostAsync(Url, tmp.Content).Result;
}
I have no idea how to put from Python code Headers (Content-Type) and additional string (payload).
If you use RestSharp, you should be able to call your service with the following code snipped
var client = new RestClient("http://url.../token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=password&username=username&password=password", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
var result = response.Content;
I based my answer on the anwser of this answer.
Here a sample I use in one of my apps:
_client = new HttpClient { BaseAddress = new Uri(ConfigManager.Api.BaseUrl),
Timeout = new TimeSpan(0, 0, 0, 0, -1) };
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.Add("Bearer", "some token goes here");
using System.Net.Http;
var content = new StringContent("grant_type=password&username=username&password=password");
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
client.PostAsync(Url, content);
Or use FormUrlEncodedContent without set header
var data = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", "username"},
{"password", "password"}
};
var content = new FormUrlEncodedContent(data);
client.PostAsync(Url, content);
If you write UWP application, use HttpStringContent or HttpFormUrlEncodedContent instead in Windows.Web.Http.dll.
using Windows.Web.Http;
var content = new HttpStringContent("grant_type=password&username=username&password=password");
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
client.PostAsync(Url, content);
var data = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", "username"},
{"password", "password"}
};
var content = new FormUrlEncodedContent(data);
client.PostAsync(Url, content);

HttpClient sending parameter null

I'm trying to send data to an api with HttpClient but parameter I'm sending keeps received as 0.
What am I doing wrong here? It's my first usage of HttpClient so it's quite possible I mixed things or made some rookie mistake.
Path is correct, I can get results from Postman.
Code I'm using is this;
static async Task GetActivityList()
{
string uri = "/api/ExtraNet/GetActivityList";
HttpClient client = new HttpClient();
int SalesPersonId = 553;
string token = my token value is here;
client.BaseAddress = new Uri("http://localhost:16513/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var postData = "{\"SalesPersonId=\":\""+SalesPersonId+"\"}";
var stringContent = new StringContent( "{\"SalesPersonId=\":\"" + SalesPersonId + "\"}", Encoding.UTF8, "application/json") ;
var content = new StringContent(postData, Encoding.UTF8, "application/json");
var response = await client.PostAsync("http://localhost:16513/api/ExtraNet/GetActivityList", stringContent);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
I managed to send the parameter this way
string uri = "/api/ExtraNet/GetActivityList";
HttpClient client = new HttpClient();
int SalesPersonId = 553;
string token = "";
client.BaseAddress = new Uri("http://localhost:16513/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var stringContent = new FormUrlEncodedContent(new[] {
new KeyValuePair<string,string>("SalesPersonId","553")
});
var response = await client.PostAsync(uri, stringContent);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
Sending the parameters as FormUrlEncodedContent did the trick.

Categories

Resources