Error while trying to get data from httprequest - c#

I'm trying to build an application that gets data from a webservice and allows me to process it in my application.
The data I need is being published on a website so in order to get access to the data I had to use the Developer Tools to try and find the call that returns the data on the website.
I have found the call and I can see the requests which are being made so as a first step I'm trying to mimic this call so I get the same results before I do anything else.
However, when I request the data, I'm getting an error stating:
key must be a string at line 1 column 2
So I'm asssuming there's something wrong with the data I'm sending in the body of my request but I don't know what.
Since the error states that the "Key" must be a string, I thought that I might had to use a Key/Value pair but I can clearly see in the Developer Tools that there is a content type mentioned:
content-type: application/json
so it seems to me that I need to send JSON.
Also when I look at the Request Payload I am seeing a JSON-formatted string being sent:
{"query":"\n query getData {\n other data which I have removed for clarity \n }\n "}
So even when I copy the entire string that I see in the Developer Tools and send that as a JSON-formatted string to the service. I still get the errormessage.
Below is the code that I'm using:
using (var client = new HttpClient())
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
client.BaseAddress = new Uri("https://api.thesite.com");
string json = "{'query':'\n query getData {\n yada yada yada ... }\n '}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
var result = await client.PostAsync("/data/history", content);
string resultContent = await result.Content.ReadAsStringAsync();
}
I know it's difficult to troubleshoot it like that without having access to the actual data itself. But I'm not looking for someone to fix the problem for me, I'm just trying to understand what the problem actually is.
Am I using the wrong functions? Do I need to actually encode it in JSON again and then serialize it into a json instead of using the actual serialized JSON-string?
Those are the things I'm wondering right now.
I hope someone can enlighten me.
Thanks

Related

How to call ChatGPT from C# using HttpClientFactory, I keep getting errors and no responses

Getting really irritated with this. The playground gives only python and node, trying to use this in C# and I keep getting errors. Here is how I have it setup.
First in the Program / Startup file, I am setting it up like so: (URL: https://api.openai.com/)
services.AddHttpClient("ChatGptAPI", client =>
{
client.DefaultRequestHeaders.Clear();
client.BaseAddress = aiOptions.Url;
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + aiOptions.Bearer);
});
Then in my method, I am calling this:
var client = _httpFactory.CreateClient("ChatGptAPI");
var payload = new
{
prompt = $"Create a first person story\n\n{storyText}",
temperature = "0.5",
max_tokens = "1500",
model = "text-davinci-003"
};
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await client.PostAsync("v1/completions", content);
Console.WriteLine("ChatGptAPI result:");
Console.WriteLine(response.RequestMessage);
I at first I kept getting Bad Request errors, but once I tried other URLs for the request, it appears to go through, but the response is blank.
For the life of me, I cannot find any samples out there that has C# calling these services.
Any help would be great.
I have tried multiple URLs, I've tried running this in Playground and view code and I've searched for other samples, but this keeps failing or returning nothing. Also tried using the OpenAI Nuget package, that was a waste of time.
If you are actually managing to reach the completions endpoint and you have a valid key then you are just reading the wrong object back.
After you get your response you should read it, something like:
var gptResponse = await response.Content.ReadAsStringAsync();
you can then parse or better deserialize the API response

Issue while creating product using Shopify API

I am experiencing a weird issue while exporting some products to Shopify. When I save a JSON generated using JSON.net to txt file and then read it and then send it to Shopify's create product API, it works fine. However, if I just save the JSON to string and send post request directly, I get a 502 gateway error from Shopify. This happens only when creating certain products, where the JSON payload is somewhat bigger than normal. On other products, just saving JSON to a string and then sending to Shopify works OK. Weirdly, when I save the JSON to file from C#, then read that file a few lines below in the same code, and use that content as JSON string and send a post request, it again doesn't work. What do you think could be the issue?
Here's the JSON generated using JSON.net which works OK when read from file (https://pastebin.com/9SKFPjGJ)
var jsonContent = JsonConvert.SerializeObject(myObject);
using (var requestMessage = new HttpRequestMessage(HttpMethod.Put, $"https://{shopifySlug}.myshopify.com/admin/products/{originalShopifyProductId}.json"))
{
requestMessage.AddShopifyHeaders(shopifyAccessToken); // just a method for adding necessary shopify headers
requestMessage.Content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
response = await client.SendAsync(requestMessage);
}
Its getting hard for me to know the reason.
Here's what works:
Code that works:
json.txt was generated using this separately:
System.IO.File.WriteAllText("E:\\json.txt",JsonConvert.SerializeObject(myObject));
(Note that if the above line of code is inserted before the code below in the same file, then the code below doesn't work, i.e. the file has to be saved separately for it to work).
And then, just reading the JSON from file and sending that in the POST request works. Code below:
var jsonContent = System.IO.File.ReadAllText("E:\\json.txt");
using (var requestMessage = new HttpRequestMessage(HttpMethod.Put, $"https://{shopifySlug}.myshopify.com/admin/products/{originalShopifyProductId}.json"))
{
requestMessage.AddShopifyHeaders(shopifyAccessToken); // just a method for adding necessary shopify headers
requestMessage.Content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
response = await client.SendAsync(requestMessage);
}
Also the not working code at the very top works OK for smaller JSON payloads like this one https://pastebin.com/RhYjVuvv

Is there a way to retrieve the String the way it is actually uploaded to the server (as a whole)?

I am currently working on a OAuth2 implementation. However I am stuck on an Error 401. It seems like there is something wrong with my post request that is supposed to retrieve the access token from the Company the User logged in to. This is my code:
internal void RequestAccessToken(string code)
{
string requestBody = "grant_type="+ WebUtility.UrlEncode(GRANTTYPE)+ "&code=" + WebUtility.UrlEncode(code)+"&redirect_uri="+ WebUtility.UrlEncode(REDIRECT_URI);
WebClient client = new WebClient();
client.Headers.Add("Authorization",HeaderBase64Encode(CLIENT_ID, SECRETKEY));
var response = client.UploadString("https://thewebsiteiamcallingto.com/some/api", requestBody);
var responseString = client.OpenRead("https://thewebsiteiamcallingto.com/some/api");
}
My Questions are:
Is there anything wrong with the way I try to make the POST request ?
Is there a way to retrieve the whole string that is posted to the URI using UploadString?
P.S. I have seen this post regarding the POST creation. However I find the async part to be too complicated for my case.
Since we dont know the api documentation, I would suggest you to make a postman request and view the actual request sent and response received, and secondly make a request using your method and capture using a utility like wireshark and compare the difference.

The request body did not contain the specified number of bytes

I am calling an API from by C# Windows service. In some cases the following error is being raised.
The request body did not contain the specified number of bytes. Got 101,379, expected 102,044
In the RAW Request captured using fiddler content length as specified.
Content-Length: 102044
In the response from the API I am receiving the following message.
The request body did not contain the specified number of bytes. Got 101,379, expected 102,044
The strange thing for me is that it does not happen for each and every request, it is generated randomly and different points. Code which I am using to get the content length is specified below.
var data = Encoding.ASCII.GetBytes(requestBody); // requestBody is the JSON String
webReqeust.ContentLength = data.Length;
Is it mandatory to provide content length in REST API calls ?
Edit 1:
This is what my sample code looks like for web request
webReqeust = (HttpWebRequest)WebRequest.Create(string.Format("{0}{1}", requestURI, queryString));
webReqeust.Method = RequestMethod.ToString();
webReqeust.Headers.Add("Authorization", string.Format("{0} {1}", token_type, access_token));
webReqeust.Method = RequestMethod.ToString();
webReqeust.ContentType = "application/json";
var data = Encoding.ASCII.GetBytes(requestBody);
webReqeust.ContentLength = data.Length;
using (var streamWriter = new StreamWriter(webReqeust.GetRequestStream()))
{
streamWriter.Write(requestBody);
streamWriter.Flush();
streamWriter.Close();
}
I would suggest maybe instead try using HttpClient as done in the linked post from mjwills here. You don't have to use content length, but it sounds like that is being enforced by the API and ultimately you are trying to post too much.
Otherwise the way I see it is that something is making the request body too large. Is it serialized input data which gets encoded into a byte array? If that is what is happening then perhaps the correct length requirements are not being enforced on the data that composes the request body, and I would suggest inspecting what goes on in the composition of the request body object itself.

What is the equivalent of using StringContent (System.Net.Http) to make a post request in Python

I have some C# code that does the following post request:
string postData = newFormUrlEncodedContent(params).ReadAsStringAsync().Result;
var postContent = new StringContent(postData, UTF8Encoding.UTF8, "application/x-www-form-urlencoded");
var responseMessage = httpClient.PostAsync(url, postContent).Result;
I would like to do the equivalent in Python using the Requests library. This is what I have:
headers = {'content-type':'application/x-www-form-urlencoded'}
postContent = requests.post(url, params=params, headers=headers, cookies=previousResponse.cookies)
But postContent.status_code for the Python code is 404, whereas the C# request returns 200. It's possible that there's something wrong with the params since I retrieve those via some Regex matching from a previous request, but that seems to be working.
Edit: I think setting the params parameter is for get requests, not post requests. Also I believe Requests takes care of form encoding:
Typically, you want to send some form-encoded data — much like an HTML form. To do this, simply pass a dictionary to the data argument. Your dictionary of data will automatically be form-encoded when the request is made
So now I have:
postContent = requests.post(url, data = params, cookies = previousResponse.cookies)
Now postContent.status_code == 500. The stack trace says the data is invalid at the root level. I will look into it.

Categories