after doing some research I got to know that it's best to instantiate HttpClient once and then reuse it's instance everwhere else.
My GetAsync requests are working absolutely fine. However, with PostAsync I'm getting error.
Please find my code below :
using System;
using System.Net.Http;
using System.Text;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Net.Mime;
namespace ConsoleApplication
{
public class Program
{
private static HttpClient client = new HttpClient();
public static async Task Main(string[] args)
{
string Event_MSG ="[{\"ID\":354,\"EventTimeStamp\":\"2022-05-
17T05:35:25\",\"Title\":\"Failedtoretrieveequipmentlogs\",\"ControllerId\":24,
\"Details\":\"UnabletoretrievelogsfromdeviceP25-SC-
023322.Cyclepoweratfieldunit.Iftheproblemreturns,contactyourHunterrepresentative.\",
\"ControllerName\":\"P25-SC-0233\"},{\"ID\":353,\"EventTimeStamp\":\"2022-05-
17T05:34:20\",\"Title\":\"Failedtoretrieveequipmentlogs\",\"ControllerId\":17,
\"Details\":\"UnabletoretrievelogsfromdeviceP25-SC-
022615.Cyclepoweratfieldunit.Iftheproblemreturns,contactyourHunterrepresentative.\",
\"ControllerName\":\"P25-SC-0226\"},{\"ID\":352,\"EventTimeStamp\":\"2022-05-
17T05:33:50\",\"Title\":\"Failedtoretrieveequipmentlogs\",\"ControllerId\":16,
\"Details\":\"UnabletoretrievelogsfromdeviceP25-SC-
022514.Cyclepoweratfieldunit.Iftheproblemreturns,contactyourHunterrepresentative.\",
\"ControllerName\":\"P25-SC-0225\"},{\"ID\":351,\"EventTimeStamp\":\"2022-05-
17T05:33:20\",\"Title\":\"Failedtoretrieveequipmentlogs\",\"ControllerId\":15,
\"Details\":\"UnabletoretrievelogsfromdeviceP25-SC-
022413.Cyclepoweratfieldunit.Iftheproblemreturns,contactyourHunterrepresentative.\",
\"ControllerName\":\"P25-SC-0224\"},{\"ID\":350,\"EventTimeStamp\":\"2022-05-
17T05:32:50\",\"Title\":\"Failedtoretrieveequipmentlogs\",\"ControllerId\":14,
\"Details\":\"UnabletoretrievelogsfromdeviceP25-SC-
022312.Cyclepoweratfieldunit.Iftheproblemreturns,contactyourHunterrepresentative.\",
\"ControllerName\":\"P25-SC-0223\"}]";
Console.WriteLine("Starting connections");
List<KeyValue> keyvalue = JsonConvert.DeserializeObject<List<KeyValue>>(Event_MSG);
JArray EventMSG = JArray.Parse(Event_MSG);
int i = 0;
foreach(var item in EventMSG)
{
var inc_val = i++;
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Basic","auth_val");
HttpResponseMessage get_response = await
client.GetAsync("https://myurl.com/"+keyvalue[inc_val]);
var get_responseString = await get_response.Content.ReadAsStringAsync();
JObject obj = JObject.Parse(get_responseString);
string DeviceID = (string) obj["managedObject"]["id"];
string isoTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
string c8y_payloadString = $"{{\"time\": \"{isoTime}\",\"source\": {{\"id\": \"
{DeviceID}\" }},\"type\": \"c8y_Golf_Controller\",\"text\": \"PilotCC Event\"}}";
JObject c8y_payloadObject = JObject.Parse(c8y_payloadString);
var c8y_finalPayload = new JObject();
c8y_finalPayload.Merge(item);
c8y_finalPayload.Merge(c8y_payloadObject);
string c8y_finalPayloadString = JsonConvert.SerializeObject(c8y_finalPayload);
Console.WriteLine(get_responseString);
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.com.nsn.cumulocity.event+json");
var stringContent = new StringContent(c8y_finalPayloadString, Encoding.UTF8,
MediaTypeNames.Application.Json);
stringContent.Headers.ContentType.CharSet = "";
HttpResponseMessage response = await client.PostAsync("https://myurl.com",
stringContent);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
Console.WriteLine("Connections done");
}
}
public class KeyValue
{
[JsonProperty("ControllerName")]
public string ControllerName { get; set; }
public override string ToString()
{
return String.Format(ControllerName);
}
}
}
Now If I remove the following lines from the code, it works completely fine and returns correct json response for all 5 get requests :
POST REQUEST CODE
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.com.nsn.cumulocity.event+json");
var stringContent = new StringContent(c8y_finalPayloadString, Encoding.UTF8,
MediaTypeNames.Application.Json);
stringContent.Headers.ContentType.CharSet = "";
HttpResponseMessage response = await client.PostAsync("https://myurl.com", stringContent);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
But when I'm using this it throws an error : -
Unhandled exception. Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Path '', line 0, position 0.
at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JObject.Parse(String json, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JObject.Parse(String json)
at ConsoleApplication.Program.Main(String[] args) in Program.cs:line 31
at ConsoleApplication.Program.<Main>(String[] args)
Only the first iteration runs successfully making both GetAsync and PostAsync calls, after that I get the above error.
Line which is throwing error is : JObject obj = JObject.Parse(get_responseString); and it is because in second iteration the get request is not returning any response(happening only when the lines in POST REQUEST CODE are included)
Sample Get Request response : -
{"managedObject":{"self":"https://url.co/inventory/managedObjects/43432113",
"id":"43432113"},"externalId":"P25-SC-0233","self":"https://url.co/identity/externalIds/c8y_Serial/P25-SC-0233",
"type":"c8y_Serial"}
What am I missing here?
Related
I'm trying after "converted/optimized" a C# Unity Project to my Visual Studio in C# to work for me (the code)...
i used this github lib for nft.storage
https://github.com/filipepolizel/unity-nft-storage/blob/main/NFTStorageClient.cs
If i call then with:
string pathtofile = #"" + AppDomain.CurrentDomain.BaseDirectory + "testfile.txt";
await NFTStorageTest.Upload(NFTStorageTest.nftStorageApiUrl, pathtofile);
i get this error:
System.Net.Http.HttpRequestException: Response status code does not indicate success: 404 (Not Found). at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at Main.net.NFTStorageTest.Upload(String uri, String pathFile) in C:\...\NFTStorageTest.cs:line 173
Here is my Code:
// nft.storage API endpoint
internal static readonly string nftStorageApiUrl = "https://api.nft.storage/";
// HTTP client to communicate with nft.storage
internal static readonly HttpClient nftClient = new HttpClient();
// http client to communicate with IPFS API
internal static readonly HttpClient ipfsClient = new HttpClient();
// nft.storage API key
public string apiToken = "XXX";
public void Start()
{
nftClient.DefaultRequestHeaders.Add("Accept", "application/json");
if (apiToken != null)
{
nftClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + apiToken);
}
else
{
// log in console in case no API key is found during initialization
Console.WriteLine("Starting NFT Storage Client without API key, please call 'SetApiToken' method before using class methods.");
}
}
public async Task<NFTStorageUploadResponse> UploadDataFromFile(string path)
{
StreamReader reader = new StreamReader(path);
string data = reader.ReadToEnd();
reader.Close();
Console.WriteLine("Uploading...");
return await UploadDataFromString(data);
}
public async Task<NFTStorageUploadResponse> UploadDataFromString(string data)
{
string requestUri = nftStorageApiUrl + "/upload";
string rawResponse = await Upload(requestUri, data);
string jsonString = JsonConvert.SerializeObject(rawResponse);
NFTStorageUploadResponse parsedResponse = JsonConvert.DeserializeObject<NFTStorageUploadResponse>(jsonString);
return parsedResponse;
}
public static async Task<string> Upload(string uri, string pathFile)
{
byte[] bytes = File.ReadAllBytes(pathFile);
using (var content = new ByteArrayContent(bytes))
{
content.Headers.ContentType = new MediaTypeHeaderValue("*/*");
//Send it
var response = await nftClient.PostAsync(uri, content);
response.EnsureSuccessStatusCode();
Stream responseStream = await response.Content.ReadAsStreamAsync();
StreamReader reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
}`
whats my mistake and how can i fix it?
await NFTStorageTest.Upload(NFTStorageTest.nftStorageApiUrl, pathtofile);
This should be called with
$”{NFTStorageTest.nftStorageApiUrl}upload”
See the original file
https://github.com/filipepolizel/unity-nft-storage/blob/45bedb5c421982645bc9bf49d12beed8f2cdb9d3/NFTStorageClient.cs#L297
I am currently trying to make an api call in c# using a MultiPartFormDataContent but I keep
getting the following error:
"Response: {"statusCode":400,"error":"Bad Request","message":""Image file" must be of type object","validation":{"source":"payload","keys":["images"]}}"
This is my Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Example
{
public class Test
{
public static void Main(string[] args)
{
Task<string> test = testFunction();
Console.WriteLine("Result: " + test.Result);
}
public static async Task<string> testFunction()
{
const string file = "C:\\ExamplePath\\image_1.jpeg";
const string URL = "https://example-api?api-key=example-key";
string boundary = "---8d0f01e6b3b5dafaaadaad";
MultipartFormDataContent multipartContent = new MultipartFormDataContent(boundary);
var streamContent = new StreamContent(File.Open(file, FileMode.Open));
var stringContent = new StringContent("flower");
multipartContent.Add(stringContent, "organs");
multipartContent.Add(streamContent, "images");
try
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsync(URL, multipartContent);
Console.WriteLine("Response: " + await response.Content.ReadAsStringAsync());
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine("IN METHIOD: " + content);
return content;
}
return null;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return null;
}
}
}
}
It's obviously a problem with how I am trying to do the api call but I don't know how to do it with an object instead like mentioned the error message.
This link has some good examples and where I actually got my code snippet from below.
Here's a basic example of using MultiFormDataContent:
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(username), "username");
form.Add(new StringContent(useremail), "email");
form.Add(new StringContent(password), "password");
form.Add(new ByteArrayContent(file_bytes, 0, file_bytes.Length), "profile_pic", "hello1.jpg");
HttpResponseMessage response = await httpClient.PostAsync("PostUrl", form);
response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
I hope this helps or points you in the right direction.
I am trying to download string from discord webhook :("https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK")
When I normally open the site with browser string is : {"message": "Unknown Webhook", "code": 10015}
But when I do that with WebClient:
WebClient wc = new WebClient();
string site = "https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK";
string x = wc.DownloadString(site);
It gives an "404 Error". Is there a way to get that {"message": "Unknown Webhook", "code": 10015} string with c#?
A rough guess would be that it's to do with the accept header. Check the documentation for the api, but my browser sent an additional 17 headers along with the request.
The simple answer would be, use HttpClient. It's recommended for new development and also gives the correct response here:
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace discordapi_headers
{
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
var response = await client.GetAsync("https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK");
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
}
However that doesn't help if you can't. Also I'm intrigued now...
Ha! I should have listened to my own advice. For web service related stuff, you can't beat fiddler and postman. It turns out that the api is returning a custom 404 to the browser that has json content.
Unfortunately DownloadString sees the 404 and throws a WebException.
Here's an updated version that works, using HttpClient and WebClient.
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace discordapi_headers
{
class Program
{
static readonly string url = "https://discordapp.com/api/webhooks/704770710509453432/GdR4absQHKDKjUiNMpw3aIpX2tx-9Z7nmPE2Sn3TUkQDM12zUczaV-m80orh7WGVzvGK";
static async Task Main(string[] args)
{
Console.WriteLine(await UseHttpClient(url));
Console.WriteLine(await UseWebClient(url));
}
private static async Task<string> UseHttpClient(string url)
{
var client = new HttpClient();
var response = await client.GetAsync(url);
return await response.Content.ReadAsStringAsync();
}
private static async Task<string> UseWebClient(string url)
{
var client = new WebClient();
try
{
var response = await client.DownloadStringTaskAsync(url);
return response;
}
catch (WebException wex)
{
using (var s = wex.Response.GetResponseStream())
{
var buffer = new byte[wex.Response.ContentLength];
var contentBytes = await s.ReadAsync(buffer, 0, buffer.Length);
var content = Encoding.UTF8.GetString(buffer);
return content;
}
}
}
}
}
I have various HttpClient calls which return back a json string. I am currently using the following code to convert the string to a custom 'object' model I have:
public static async Task<List<Models.GSAModels.Meeting>> GetMeetingsAndRacesOnDate(DateTime date)
{
string res = "";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
using (HttpResponseMessage response = await client.GetAsync("url" + date.ToString("yyyy-MM-dd") + "?gsaappkey=9999"))
{
res = await response.Content.ReadAsStringAsync();
}
}
JObject jobject = JObject.Parse(res);
List<Models.GSAModels.Meeting> list = jobject["value"].ToObject<List<Models.GSAModels.Meeting>>();
return list;
}
Is this the most effecient way of doing so?
Thank you
You can use Newtownsoft.Json nuget package
using Newtonsoft.Json;
...
var result = JsonConvert.DeserializeObject<T>(json);
I have a web request that is working properly, but it is just returning the status OK, but I need the object I am asking for it to return. I am not sure how to get the json value I am requesting. I am new to using the object HttpClient, is there a property I am missing out on? I really need the returning object. Thanks for any help
Making the call - runs fine returns the status OK.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMsg = client.GetAsync(string.Format("http://localhost:5057/api/Photo")).Result;
The api get method
//Cut out alot of code but you get the idea
public string Get()
{
return JsonConvert.SerializeObject(returnedPhoto);
}
If you are referring to the System.Net.HttpClient in .NET 4.5, you can get the content returned by GetAsync using the HttpResponseMessage.Content property as an HttpContent-derived object. You can then read the contents to a string using the HttpContent.ReadAsStringAsync method or as a stream using the ReadAsStreamAsync method.
The HttpClient class documentation includes this example:
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Building on #Panagiotis Kanavos' answer, here's a working method as example which will also return the response as an object instead of a string:
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json; // Nuget Package
public static async Task<object> PostCallAPI(string url, object jsonObject)
{
try
{
using (HttpClient client = new HttpClient())
{
var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
if (response != null)
{
var jsonString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<object>(jsonString);
}
}
}
catch (Exception ex)
{
myCustomLogger.LogException(ex);
}
return null;
}
Keep in mind that this is only an example and that you'd probably would like to use HttpClient as a shared instance instead of using it in a using-clause.
Install this nuget package from Microsoft System.Net.Http.Json. It contains extension methods.
Then add using System.Net.Http.Json
Now, you'll be able to see these methods:
So you can now do this:
await httpClient.GetFromJsonAsync<IList<WeatherForecast>>("weatherforecast");
Source: https://www.stevejgordon.co.uk/sending-and-receiving-json-using-httpclient-with-system-net-http-json
I think the shortest way is:
var client = new HttpClient();
string reqUrl = $"http://myhost.mydomain.com/api/products/{ProdId}";
var prodResp = await client.GetAsync(reqUrl);
if (!prodResp.IsSuccessStatusCode){
FailRequirement();
}
var prods = await prodResp.Content.ReadAsAsync<Products>();
What I normally do, similar to answer one:
var response = await httpClient.GetAsync(completeURL); // http://192.168.0.1:915/api/Controller/Object
if (response.IsSuccessStatusCode == true)
{
string res = await response.Content.ReadAsStringAsync();
var content = Json.Deserialize<Model>(res);
// do whatever you need with the JSON which is in 'content'
// ex: int id = content.Id;
Navigate();
return true;
}
else
{
await JSRuntime.Current.InvokeAsync<string>("alert", "Warning, the credentials you have entered are incorrect.");
return false;
}
Where 'model' is your C# model class.
It's working fine for me by the following way -
public async Task<object> TestMethod(TestModel model)
{
try
{
var apicallObject = new
{
Id= model.Id,
name= model.Name
};
if (apicallObject != null)
{
var bodyContent = JsonConvert.SerializeObject(apicallObject);
using (HttpClient client = new HttpClient())
{
var content = new StringContent(bodyContent.ToString(), Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
client.DefaultRequestHeaders.Add("access-token", _token); // _token = access token
var response = await client.PostAsync(_url, content); // _url =api endpoint url
if (response != null)
{
var jsonString = await response.Content.ReadAsStringAsync();
try
{
var result = JsonConvert.DeserializeObject<TestModel2>(jsonString); // TestModel2 = deserialize object
}
catch (Exception e){
//msg
throw e;
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return null;
}
The code below is to access your HttpResponseMessage and extract your response from HttpContent.
string result = ret.Result.Content.ReadAsStringAsync().Result;
Convert your json in a structure according with your business
In my case BatchPDF is a complex object that it is being populated by result variable.
BatchPDF batchJson = JsonConvert.DeserializeObject<BatchPDF>(result);
return batchJson;