Woocomerce : Update a product doesn't work - c#

I'm trying to update a product's informations to the WooCommerce shop, from a windows service as follows:
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
string encoded = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encoded);
var _url = $"{WooUrl}/wp-json/wc/v3/products/{id}";
//var request = new HttpRequestMessage(HttpMethod.Post, _url);
////request.SetTimeout(TimeSpan.FromSeconds(10));
var requestBody = JsonConvert.SerializeObject(p);
//request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var response = await client.PostAsync(_url, new StringContent(requestBody, Encoding.UTF8, "application/json"));
}
But I'm getting trouble as the await doesn't finish even the update is done in the website, because i need the response data.
Assuming that the same request is working from Postman when it's simulated.
How to resolve this issue?
thanks.

i figure out the issue finally. By calling .Result, i was blocking the main thread, which causes a deadlock and the postasync doesn't return.
I change my handler to async void and use await instead.

Related

HttpClient request no response

I am not getting any response - no error, no bad request status, etc. - when I send a post request to this API route. postData is simply a JSON object. The funny thing here is this: When i send post data as a string instead of an object, I can get a response.
View the code below:
[HttpPost]
[Route("api/updateStaffs/")]
public async Task<object> UpdateStaff([FromBody] object postData)
{
string _apiUrl = "http://localhost:5000/system/getToken";
string _baseAddress = "http://localhost:5000/system/getToken";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = await client.PostAsync(_apiUrl, new StringContent(postData.ToString(), Encoding.UTF8, "application/json"));
if (responseMessage.IsSuccessStatusCode)
{
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = responseMessage.Content;
return ResponseMessage(response);
}
}
return NotFound();
}
No response:
var postData = new {
user = "test"
pass = "hey"
};
var responseMessage = await client.PostAsync(_apiUrl, new StringContent(postData.ToString(), Encoding.UTF8, "application/json"));
OR
var responseMessage = await client.PostAsync(_apiUrl, new StringContent("{}", Encoding.UTF8, "application/json"));
Will get response:
var responseMessage = await client.PostAsync(_apiUrl, new StringContent("blahblah", Encoding.UTF8, "application/json"));
The receiving API is a third-party application so I am unable to verify if this error is on the other end.
Thanks.
If you dont want to use PostAsJsonAsync
You need to serialize your anonymous type to JSON, the most common tool for this is Json.NET
var jsonData = JsonConvert.SerializeObject(postData);
Then you need to construct a content object to send this data, here we can use ByteArrayContent but you can use a different type
var buffer = System.Text.Encoding.UTF8.GetBytes(jsonData);
var byteContent = new ByteArrayContent(buffer);
Then send the request
var responseMessage = await client.PostAsync(_apiUrl, byteContent);
Figured out the issue. Have to use HttpVersion10 instead of HttpVersion11.

Calling an api using httpClient PostAsync - 400 Bad Request

There has been a lot of similar questioning on this one but I could not get any answers working for me..
I am calling another api Post request from my controller..but I get a 400 bad request all the time..
public async Task<JsonResult> TestSCIMPost(AppAuth auth)
{
//Method 3:
HttpClient client = new HttpClient();
var jsonRequest = Newtonsoft.Json.JsonConvert.SerializeObject(auth);
var content = new StringContent(jsonRequest);
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "application/json");
HttpResponseMessage response = await client.PostAsJsonAsync(
URL, content);
return new JsonResult(response);
}
curl
curl -X POST "https://localhost:5001/api/Employee/api/Employee/TestSCIMPost" -H "accept: /" -H "Content-Type: application/json-patch+json" -d "{"client_id":"xyz","grant_type":"cc","client_secret":"abc","scope":"read"}"
I have tried a couple of other ways that I am listing below..
public async Task<JsonResult> TestSCIMPost(AppAuth auth)
{
/*var response = string.Empty;
var jsonRequest = Newtonsoft.Json.JsonConvert.SerializeObject(auth);
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(jsonRequest);
var content = new ByteArrayContent(messageBytes);
//HttpContent c = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "application/json");
//content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
using (var client = new HttpClient())
{
//client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage result = await client.PostAsync(URL, content);
if (result.IsSuccessStatusCode)
{
response = result.StatusCode.ToString();
}
}*/
//Method:2
//HttpClient client = new HttpClient();
//client.BaseAddress = new Uri(URL);
//client.DefaultRequestHeaders.Accept.Clear();
//client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
//var requestMessage = Newtonsoft.Json.JsonConvert.SerializeObject(auth);
//var content = new StringContent(requestMessage, Encoding.UTF8, "application/json");
//content.Headers.Remove("Content-Type");
//content.Headers.Add("Content-Type", "application/json");
//HttpResponseMessage result = await client.PostAsync(URL, content);
return new JsonResult(response);
}
The body is coming from auth (frontend that i am serializing and adding in my request)
What's going wrong here? Is it utf-encoding? how to fix?
One reason this can happen is if you are posting content in the body (as you are doing) where the parser expects to find it in the query.
So if you have something like this:
string url = "https://localhost:5001/api/Employee/TestSCIMPost";
var content = new StringContent("{\"client_id\":\"xyz\",\"grant_type\":\"cc\"}");
HttpResponseMessage response = await client.PostAsync(url, content);
Try changing it to this:
string url = "https://localhost:5001/api/Employee/TestSCIMPost?client_id=xyz&grant_type=cc";
var content = new StringContent("");
HttpResponseMessage response = await client.PostAsync(url, content);

why An error is created when creating the token

public static void CreateToken()
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("grant_type", "client_credentials");
var UserPassJson = "{\"username\": \"mucode\",\"password\": \"mypassword\"}";
HttpContent content = new StringContent(UserPassJson, Encoding.UTF8, "application/json");
var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v1/oauth2/token"), content).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
Console.WriteLine(responseString);
}
}
why response.IsSuccessStatusCode Showing status code 401? What causes the malfunction?
What action does cause success?
The documentation specifies that you should pass the username and password using basic authentication and that you should pass a form-encoded body containing grant_type=client_credentials.
At the moment your code adds grant_type as a header, and posts the username and password as a JSON object in the body.
Correcting your code to do it the way the documentation says, we get:
HttpClient client = new HttpClient();
byte[] authBytes = System.Text.Encoding.ASCII.GetBytes("mucode:mypassword");
string base64Auth = Convert.ToBase64String(authBytes);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", base64Auth);
HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "client_credentials") });
var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v1/oauth2/token"), content).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
string responseString = responseContent.ReadAsStringAsync().Result;
Console.WriteLine(responseString);
}
P.S. I recommend reading You're using HttpClient wrong and it is destabilizing your software and the follow-up You're (probably still) using HttpClient wrong and it is destabilizing your software. I also recommend making this method async and making the chain all the way up async too.

C# HttpClient POST request pass already encoded data

I have already encoded data that wants to pass as is the String to HttpClient PostRequest
but FormUrlEncodedContent only accepts a dictonary as parameter
I want something like client.PostAsync(url, plain_string_content)
var content = new FormUrlEncodedContent(values);
using (var client = new HttpClient())
{
try
{
var response = client.PostAsync(url, content).GetAwaiter().GetResult();
string resp=response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
return resp;
}
You may use HttpClient.SendAsync:
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post);
request.Content = new StringContent(plain_string_content);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
await client.SendAsync(request);
Note that, after all, PostAsync and other HttpClient's methods are shortcuts of SendAsync.

Set Authorization Header of HttpClient

I have the following code, and I want to set the Authorization of the post request to be like this:
Authorization:key=somevalue
using (HttpClient client = new HttpClient())
{
using (StringContent jsonContent = new StringContent(json))
{
jsonContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (HttpResponseMessage response = await client.PostAsync("https://android.googleapis.com/gcm/send", jsonContent))
{
var reponseString = await response.Content.ReadAsStringAsync();
}
}
}
how to do this? I am really struggling
and the following statement
client.DefaultRequestHeaders.Add("Authorization", "key=" + apiKey);
thrown the following exception
An exception of type 'System.FormatException' occurred in
System.Net.Http.dll but was not handled in user code
I solved this by the following line of code.
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("key", "=" + apiKey);
Not sure if this is still running, but basic auth key and something like a 64 hash authed key would be added to something like a REST call like:
var httpClient2 = new HttpClient();
var uri = new Uri("<someuri>");
var tokenKey = "<sometokenkey>");
var httpContent = new StringContent("<some body or serialized thing>", System.Text.Encoding.UTF8, "application/json");
httpClient2.BaseAddress = new Uri(uri);
httpClient2.DefaultRequestHeaders.Accept.Clear();
httpClient2.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", tokenKey);
response = await httpClient2.PostAsync(uri, httpContent);
I had the same problem, I solved using :
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);
request.Headers["Authorization"] = "Basic jMxMTgwMWUzYWFkYTk4NjM2MjcyOTk3MDowYTU0N2I2NzliNWRkMjliN2I4NTFlMDBkY2Y2NjQzNzQ5OTIxYzZl";
where the string after Basic is an encoded string from Postman, the option is 'code'.
I hope this helps!

Categories