I need to send a POST request with usage of HttpClient, what i have right now:
[Route("RegisterTransaction")]
[HttpPost]
public async Task<ActionResult<string>> RegisterTransaction()
{
var httpClient = this._httpClientFactory.CreateClient();
try
{
string jsonData = "{\"sessionId\":\"1\"," +
"\"merchantId\":00000," +
"\"amount\":2137," +
"\"currency\":\"PLN\"," +
"\"crc\":\"xxxxxxxx\"}";
byte[] byteArray = Encoding.UTF8.GetBytes(jsonData);
SHA384 shaM = new SHA384Managed();
var hashResult = shaM.ComputeHash(byteArray);
string stringHashResult = BitConverter.ToString(hashResult).Replace("-", String.Empty).ToLower();
using (var client = new HttpClient())
{
// Set the base address and headers for the request
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
// Set the Basic Authentication header
var authValue = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{merchantId}:{clientSecret}"));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authValue);
var urlReturn = System.Web.HttpUtility.UrlEncode("http://sample.com/");
var payload =
"{" +
"\"merchantId\":" + $"{merchantId}" + "," +
"\"posId\":" + $"{merchantId}" + "," +
"\"sessionId\":" + "\"1\"" + "," +
"\"amount\":" + "2137" + "," +
"\"currency\":" + "\"PLN\"" + "," +
"\"description\":" + "\"test_from_c#\"" + "," +
"\"email\":" + "\"sample#gmail.com\"" + "," +
"\"country\":" + "\"PL\"" + "," +
"\"language\":" + "\"pl\"" + "," +
"\"urlReturn\":" + $"\"{urlReturn}\"" + "," +
"\"timeLimit\":" + "15" + "," +
"\"waitForResult\":" + "true" + "," +
"\"shipping\":" + "0" + "," +
"\"sign\":" + $"\"{stringHashResult}\"" +
"}";
var content = new StringContent(payload, Encoding.UTF8, "application/json");
// Send the POST request and get the response
var response = await client.PostAsync(uriPath, content);
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
}
return Ok();
}
catch (HttpRequestException ex)
{
return BadRequest(ex.Message);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
Problem is that, this code generates response 400:
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:{ Access-Control-Allow-Origin: * Strict-Transport-Security: max-age=16000000; includeSubDomains; preload; Cache-Control: max-age=0, no-cache, no-store Pragma: no-cache Date: Sun, 18 Dec 2022 19:52:14 GMT Connection: close Set-Cookie: PHPSESSID=20417919ff332939962473ac49ab1f1e; path=/; secure; HttpOnly Set-Cookie: akaalb_Sandbox=~op=sandbox:sandbox-dc1|~rv=60~m=sandbox-dc1:0|~os=352131486e59fe329be9d171af3005ed~id=903a75e16940cf8c12e4c2e79ee82d78; path=/; HttpOnly; Secure; SameSite=None DC: DC1 Content-Type: application/json Content-Length: 40 Expires: Sun, 18 Dec 2022 19:52:14 GMT}, Trailing Headers:{}}
with a little to no information usefull to me, while this exact same request sended from Postman is resulting in response 200.
My question is: Why is that?
Why this same payload with these same headers generating different responses? I've checked json payload and it is 100% correct, also generated hashes and username and password in header. What am I missing?
Related
I am learning Xamarin forms. I am using Google Place API for searching nearby
I have managed to call the API in .NET, but I only get 20 results as it is written in the Google document.
Here is my code :
string lati = location.Latitude.ToString().Replace(",", ".");
string longi = location.Longitude.ToString().Replace(",", ".");
string latitude = lati;
string longitude = longi;
string Myradius = "3000";
var URL = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?";
string urlParameters = "?location=" + latitude + "," + longitude + "&radius=" + Myradius + "&key=My_GOOGLE_KEY";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
// List data response.
HttpResponseMessage response = await client.GetAsync(urlParameters);
if (response.IsSuccessStatusCode)
{
JObject joResponse = JObject.Parse(await response.Content.ReadAsStringAsync());
JArray MyJsonResult = (JArray)joResponse["results"];
// I want to have the second page result of my API Call
string token = joResponse["next_page_token"].ToString(); // I have manage to get the token
JArray MyJsonResult2 = await GetnextPageData(latitude, longitude, Myradius, token); //no result
}
async Task<JArray> GetnextPageData(string latitude, string longitude, string Myradius , string token)
{
var URL = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?";
string urlParameters = "?location=" + latitude + "," + longitude + "&radius=" + Myradius + "&key=My_GOOGLE_KEY&pagetoken=" + token;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// List data response
HttpResponseMessage response = await client.GetAsync(urlParameters);
Console.WriteLine("MyPrint " + response);
if (response.IsSuccessStatusCode)
{
JObject joResponse = JObject.Parse(await response.Content.ReadAsStringAsync());
Console.WriteLine("MyPrint " + response);
JArray MyJsonResult = (JArray)joResponse["results"];
if (MyJsonResult != null)
{
return MyJsonResult;
}
else
{
return null;
}
}
return null;
}
I have found those link but still cannot add the parameter for the rest of the result:
Obtaining more than 20 results with Google Places API
How to get 20+ result from Google Places API?
Problem: I have manage to get the token but when I put it in the parameter I get no result - MyJsonResult2 is empty.
When I print "response" for the second call I have this :
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.NSUrlSessionHandler+NSUrlSessionDataTaskStreamContent, Headers:
{
server-timing: gfet4t7; dur=30
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Server: scaffolding
Server: on
Server: HTTPServer2
x-xss-protection: 0
Cache-Control: public, max-age=300
Date: Sun, 13 Nov 2022 02:19:16 GMT
X-Frame-Options: SAMEORIGIN
Vary: Accept-Language
Content-Type: application/json; charset=UTF-8
server-timing: gfet4t7; dur=30
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Content-Encoding: gzip
x-xss-protection: 0
Expires: Sun, 13 Nov 2022 02:24:16 GMT
Content-Length: 86
X-Frame-Options: SAMEORIGIN
}
And when I print "joResponse" for the second call I have this :
{
"html_attributions": [],
"results": [],
"status": "INVALID_REQUEST"
}
Thanks for your help.
I have found the solution. I must add in my request the parameters :"hasNextPage=true&nextPage()=true"
I try to bring the pdf file into a standard software, wrote the code, an exception is issued because of wrong format with json although json string corresponds exactly to the specified json of api call of standard software. can you please take a look if I wrote something wrong here or if I forgot something?
I covered some information with a star
Many Thanks
IRestResponse response3;
client = new RestClient("http://***.***.***.*");
client.Authenticator = new HttpBasicAuthenticator("********", "*********");
client.Timeout = -1;
request = new RestRequest("/*****/api/******/*****/***", Method.POST);
request.AddHeader("content-type", "multipart/form-data");
request.AlwaysMultipartFormData = true;
request.AddParameter("Object", "{" +
"\"cabinet\":\"Posteingang\"," +
"\"name\":\"Posteingang\"," +
"\"objectTypeId\":\"2\"," +
"\"fields\":{" +
"\"Datum\":{\"value\":\"" + DateTime.Now.ToString("dd.MM.yyyy") + "\"}" +
"}" +
"}");
request.AddFile("file","C:/Users/*********/Documents/*********/Org.pdf","Org.pdf");
MultipartFormDataContent multipartForm = new MultipartFormDataContent();
byte[] file_bytes = File.ReadAllBytes("C:/Users/********/Documents/********/Org.pdf");
multipartForm.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
multipartForm.Add(new StringContent("Object"), "{" +
"\"cabinet\":\"Posteingang\"," +
"\"name\":\"Dokument\"," +
"\"objectTypeId\":\"******\"," +
"\"fields\":{" +
"\"Datum\":{\"MAIL_SUBMIT_TIME\":{\"value\":\"" + DateTime.Now.ToString("dd.MM.yyyy") + "\"},\"Typ\":" +
"{\"feld4\":{\"value\": \"Brief\"}},\"Absender\": {\"Mail_FROM\":{\"value\": \"*********\"}}}}}");
response3 = client.Execute(request);
Console.WriteLine(response3.Content);
}
}
}
I made an auto scheduler where data is forwarded to my AWS Server.
I created a Window Service that runs every min to forward the new data.
I have an existing API that received the data in AWS Server.
Window Service works fine with API on network server
API Address1 : http:\\192.168.0.1\api\data\getdata (Working in network 100%)
API Address2 : https:\\api.mydomain.com\api\data\getdata (Tested in winform and postman
working 100%)
But encountered a problem when window services send data to API Address 2
Here is the code
public static void SendData()
{
var PostData = new Profile
{
ID = 99,
Code = "123",
Email = 'xyz#yahoo.com'
};
try
{
var PostBody = JsonConvert.SerializeObject(PostData);
var PostContent = new StringContent(PostBody, Encoding.UTF8, "application/json");
//BaseAddress = "https:\\api.mydomain.com";
using (var Client = API_Client.GetClient("api/data/getdata"))
{
var Sending = Client.PostAsync(Client.BaseAddress.ToString(), PostContent);
Sending.Wait();
var Response = Sending.Result;
if (Response.IsSuccessStatusCode)
{
Logger.WriteLine("Sending Info to API '" + PostData.ID.ToString() + "'", "Success");
}
else
{
Logger.WriteLine("Sending Info to API '" + PostData.ID.ToString() + "'", Response.ReasonPhrase);
}
}
}
catch (Exception ex)
{
Logger.WriteLine("Error '" + PostData.ID.ToString() + "' To Server", ex.Message);
}
}
Here is Error Message
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
Connection: close
Cache-Control: no-cache
Date: Thu, 13 Dec 2018 06:40:34 GMT
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 41
Content-Type: application/json; charset=utf-8
Expires: -1
}}
API Client Helper
public class API_Client
{
protected static string API_BASE_ADDRESS = "https:\\api.mydomain.com\";
public static HttpClient GetClient(string URL_Target)
{
var Client = new HttpClient()
{
BaseAddress = new Uri(API_BASE_ADDRESS + URL_Target),
Timeout = new TimeSpan(0, 0, 90)
};
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Client.DefaultRequestHeaders.ConnectionClose = true;
return Client;
}
}
Postman
Ok so I'm having a bit of trouble getting these JSON requests through to the Ebay API.
Here is the json request:
string jsonInventoryRequest = "{" +
"\"requests\": [";
int commaCount = 1;
foreach (var ep in productsToProcess)
{
jsonInventoryRequest += "{\"offers\": [{" +
"\"availableQuantity\":" + ep.EbayProductStockQuantity + "," +
"\"offerId\":\"" + ep.EbayID.ToString() + "\"," +
"\"price\": {" +
"\"currency\": \"AUD\"," +
"\"value\":\"" + ep.EbayProductPrice.ToString() + "\"" +
"}" +
"}],";
jsonInventoryRequest += "\"shipToLocationAvailability\": " + "{" +
"\"quantity\":" + ep.EbayProductStockQuantity +
"},";
jsonInventoryRequest += "\"sku\": " + ep.EbayProductSKU.ToString() + "}";
if (commaCount < productsToProcess.Count())
jsonInventoryRequest += ",";
commaCount++;
sendEbayApiRequest = true;
}
jsonInventoryRequest +=
"]" +
"}";
And the Debug.WriteLine() output of the above JSON request is :
json string = {"requests": [{"offers": [{"availableQuantity":0,"offerId":"098772298312","price": {"currency": "AUD","value":"148.39"}}],"shipToLocationAvailability": {"quantity":0},"sku": 135779},{"offers": [{"availableQuantity":1,"offerId":"044211823133","price": {"currency": "AUD","value":"148.39"}}],"shipToLocationAvailability": {"quantity":1},"sku": 133607}]}
Here is the code in C# to send the request:
var ebayAppIdSetting = _settingService.GetSettingByKey(
"ebaysetting.appid", "");
var ebayCertIdSetting = _settingService.GetSettingByKey(
"ebaysetting.certid", "");
var ebayRuNameSetting = _settingService.GetSettingByKey(
"ebaysetting.appid", "");
var stringToEncode = ebayAppIdSetting + ":" + ebayCertIdSetting;
HttpClient client = new HttpClient();
byte[] bytes = Encoding.UTF8.GetBytes(stringToEncode);
var base64string = "Basic " + System.Convert.ToBase64String(bytes);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", base64string);
var stringContent = "?grant_type=client_credentials&" + "redirect_uri=" + ebayRuNameSetting + "&scope=https://api.sandbox.ebay.com/oauth/api_scope";
var requestBody = new StringContent(stringContent.ToString(), Encoding.UTF8, "application/json");
requestBody.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var response = client.PostAsync("https://api.sandbox.ebay.com/identity/v1/oauth2/token", requestBody);
The output I get when I do Debug.WriteLine("response.Content = " + response.Result); is:
response.Content = StatusCode: 401, ReasonPhrase: 'Unauthorized',
Version: 1.1, Content: System.Net.Http.StreamContent, Headers: {
RlogId:
t6ldssk%28ciudbq%60anng%7Fu2h%3F%3Cwk%7Difvqn*14%3F0513%29pqtfwpu%29pdhcaj%7E%29fgg%7E%606%28dlh-1613f3af633-0xbd
X-EBAY-C-REQUEST-ID: ri=HNOZE3cmCr94,rci=6kMHBw5dW0vMDp8A
X-EBAY-C-VERSION: 1.0.0 X-EBAY-REQUEST-ID:
1613f3af62e.a096c6b.25e7e.ffa2b377!/identity/v1/oauth2/!10.9.108.107!r1esbngcos[]!token.unknown_grant!10.9.107.168!r1oauth-envadvcdhidzs5k[]
Connection: keep-alive Date: Mon, 29 Jan 2018 00:04:44 GMT
Set-Cookie: ebay=%5Esbf%3D%23%5E;Domain=.ebay.com;Path=/
WWW-Authenticate: Basic Content-Length: 77 Content-Type:
application/json }
Can anyone see where I'm going wrong. Cheers
Ok so the authentication was failing because I was sending wrong authentication token. Needed to get oauth token from application tokens.
So instead of base64 encoding token like this:
var base64string = "Basic " + System.Convert.ToBase64String(bytes);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", base64string);
I needed to do the following:
url = "https://api.sandbox.ebay.com/sell/inventory/v1/bulk_update_price_quantity";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
//request.ContentType = "application/json; charset=utf-8";
request.Headers.Add("Authorization", "Bearer **OAUTH TOKEN GOES HERE WITHOUT ASTERIKS**");
// Send the request
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(jsonInventoryRequest);
streamWriter.Flush();
streamWriter.Close();
}
// Get the response
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
if (response != null)
{
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
// Parse the JSON response
var result = streamReader.ReadToEnd();
}
}
I have the Odata service, in order to perform a PUT we need to set the Header with If-Match: * In Post man I giving like below and it works
How do I set this If-Match in the Odata Service call to perform a PUT operation.I tried the below
private async Task<HttpResponseMessage> PutJsonAsync(string messageBody,string B_Code)
{
string userName = ConfigurationManager.AppSettings["Username"];
string password = ConfigurationManager.AppSettings["Password"];
string BaseURL = ConfigurationManager.AppSettings["BaseURL"];
try
{
using (var httpClient = new HttpClient())
{
var request = new StringContent(messageBody, Encoding.UTF8, "application/json");
string apiUrl = "SAM('" + B_Code + "')";
request.Headers.ContentType = new MediaTypeHeaderValue("application/json");
request.Headers.TryAddWithoutValidation("If-Match", "*");
var url = string.Format("{0}{1}", BaseURL, apiUrl);
var creds = userName + ":" + password;
var credentials = Encoding.ASCII.GetBytes(creds);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(credentials));
response = await httpClient.PutAsync(new Uri(url), request);
}
}
catch (Exception ex)
{
throw ex;
}
return response;
}
But it is not working and throws error 501:Not Implemented
`response {StatusCode: 501, ReasonPhrase: 'Not Implemented', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
OData-Version: 4.0
Date: Mon, 30 Oct 2017 20:42:28 GMT
Set-Cookie: JSESSIONID=XYZ; Path=/; Secure; HttpOnly
Set-Cookie: XYZ;PATH=/;SECURE;HTTPONLY
Server: Apache-Coyote/1.1
Vary: Accept-Encoding
Connection: keep-alive
Content-Length: 277
Content-Type: application/json; odata.metadata=minimal
}} System.Net.Http.HttpResponseMessage`
Your "request" object, is your content object, not the HttpRequestMessage object. How did I realise that? ContentType isn't available on the HttpRequestMessage.
If-Match is not a content-level header (I don't know why Microsoft make this distinction). You can't add it here, you have to add it to the request header. If you add it to the content object, it gets disregarded.
Something like this should work:
string apiUrl = "SAM('" + B_Code + "')";
var url = string.Format("{0}{1}", BaseURL, apiUrl);
var creds = userName + ":" + password;
var credentials = Encoding.ASCII.GetBytes(creds);
var request = new HttpRequestMessage(HttpMethod.Put, new Uri(url));
request.Content = new StringContent(messageBody, Encoding.UTF8, "application/json");
request.Headers.TryAddWithoutValidation("If-Match", "*");
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(credentials));
response = await httpClient.SendAsync(request);