GraphQL request in C# - c#

I'm a Unity developer tool and i want to post a GraphQL request with using System.Net.Http; (i don't want to use the GraphQL dll because there are compatibility problems).
But i have this error (got on the Debug.Log) :
POST body missing, invalid Content-Type, or JSON object has no keys.
My code :
static async Task<string> getEntityID(string path)
{
var values = new Dictionary<string, string>
{
{ "query", "query {topLevelEntityTypes {id}}" },
{ "variables", "{}" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://localhost:4000/graphql", content);
var responseString = await response.Content.ReadAsStringAsync();
Debug.Log(responseString);
return responseString;
}
Thank you !

Solution by ProgrammingLlama :
static async Task<string> getEntityID(string path)
{
var myObject = new QueryJson();
myObject.query = "query {topLevelEntityTypes {id}}";
myObject.variables = "{}";
var response = await client.PostAsync("http://localhost:4000/graphql", new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(myObject), Encoding.UTF8, "application/json"));
var responseString = await response.Content.ReadAsStringAsync();
Debug.Log(responseString);
return responseString;
}
Class json
internal class QueryJson
{
public string query { get; set; }
public string variables { get; set; }
}

Related

How to reuse HttpClient reference for multiple http requests

I have a code where I am creating an instance of HttpClient, which is inside of a foreach loop. Which means it is creating a new instance for each time the iteration takes place. Here is my code :
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Text;
using System.Net.Mime;
using System.Net.Http.Json;
public class Program
{
static async Task Main(string[] args)
{
//JSON String
string json = #"{
'Values': [
{
'MsgSource': null,
'TagName': 'Data.New_MSG',
'RawValue': '[\r\n {\r\n \'ID\': 145,\r\n \'StationNo\': 6,\r\n
\'RunTime\': 1800,\r\n \'ControllerID\': 4,\r\n
\'ControllerAddress\': 2,\r\n \'ProgramNo\': 2,\r\n
\'ModeID\': \'AutoProgram\',\r\n \'EventDate\': \'2022-04-
27T23:30:02\',\r\n \'Description\': \'Irrigation
Completed\',\r\n \'MessageCode\': 5\r\n,\r\n
\'ControllerName\': \'P25-SC-0233\' },\r\n {\r\n \'ID\':
144,\r\n \'StationNo\': 18,\r\n \'RunTime\': 1800,\r\n
\'ControllerID\': 4,\r\n \'ControllerAddress\': 2,\r\n
\'ProgramNo\': 5,\r\n \'ModeID\': \'AutoProgram\',\r\n
\'EventDate\': \'2022-04-27T22:00:00\',\r\n \'Description\':
\'Irrigation Completed\',\r\n \'MessageCode\': 5\r\n,\r\n
\'ControllerName\': \'P25-SC-0226\' }\r\n]',
'Status': 'Normal',
'ComStatus': null,
'TimeStamp': '2022-04-28 13:17:39.851'
}
]
}";
//Deserializing JSON String
Root root = JsonConvert.DeserializeObject<Root>(json);
//Extracting the value of only RawValue key from the String
string rawValue = root.Values[0].RawValue;
//Creating List of ControllerName key
List<Station> stations = JsonConvert.DeserializeObject<List<Station>>(rawValue);
JArray array = JArray.Parse(rawValue);
int i = 0; //Initializing Index to add ControllerName to the URL in Get http
//request below
foreach(var item in array) //Iterating through array
{
var inc_val = i++;
using (var client = new HttpClient()) //Here I've Instantiated HttpClient
{
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Basic","auth_value"); //Basic Auth
//Mandatory key for Message body in Post request
string isoTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
//Concatenating ControllerName in URL and making get request
HttpResponseMessage get_response = await
client.GetAsync("https://myurl.com/"+stations[inc_val]);
var get_responseString = await get_response.Content.ReadAsStringAsync();
JObject obj = JObject.Parse(get_responseString);
//Extracting id from the response of Get request which has to be used in
//Post Data when making Post request
string name = (string) obj["managedObject"]["id"];
//Required JSON Body structure which needs to be merged with Post Data
string json2 = $"{{\"time\": \"{isoTime}\",\"source\": {{\"id\": \"{name}\"
}},\"type\": \"c8y_Golf_Controller\",\"text\": \"PilotCC Data New Msg\"}}";
JObject json3 = JObject.Parse(json2);
var result = new JObject();
result.Merge(item);
result.Merge(json3);
string json4 = JsonConvert.SerializeObject(result);
client.DefaultRequestHeaders.Add("Accept",
"application/vnd.com.nsn.cumulocity.event+json"); //More Headers
var stringContent = new StringContent(json4, Encoding.UTF8,
"application/json");
stringContent.Headers.ContentType.CharSet = "";
//Making Post request
HttpResponseMessage response = await client.PostAsync("https://myurl.com",
stringContent);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
}
}
public class Root
{
public List<Value> Values {get; set;}
}
public class Value
{
public string RawValue { get; set; }
}
public class Station
{
[JsonProperty("ControllerName")]
public string ControllerName { get; set; }
public override string ToString()
{
return String.Format(ControllerName);
}
}
}
How do I make it better by not creating unnecessary instances of HttpClient each time foreach loop iteration in triggered and instead reuse the single instance of HttpClient for making all the http requests??
In your case, it would be enough to ...
public class Program
{
static async Task Main()
{
// Create one single instance outside the loop ...
var client = new HttpClient();
// more code here
foreach( var item in array )
{
// ... then use it.
var response = await client.GetAsync(/* yadda yadda */);
}
}
}

C#- http client response help request

I have the following code:
static async Task checkIMEI( double IMEI)
{
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://kelpom-imei-checker1.p.rapidapi.com/api?service=model&imei=" + IMEI.ToString() ),
Headers =
{
{ "X-RapidAPI-Host", "kelpom-imei-checker1.p.rapidapi.com" },
{ "X-RapidAPI-Key", "key" },
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
object result = await response.Content.ReadAsStringAsync();
MessageBox.Show("\n" + result);
}
}
Running this code I get the following
response
I would like to further break up this response and the individual data and assign it to a variable such as
string ModelNum= model_nb >> should show "SM-G891A"
String Brand = brand >> should show "Samsung Korea"
Your help would be appriciated.
first your Client is bad practice use this link HttpClientFactory Microsoft docs to refactor your client.
Then Create Class for your needed model for ex:
public class Mobile
{
public string ModelNum { get; set; }
public string Brand { get; set; }
}
then you should deserialize your result to your model:
var result = await response.Content.ReadAsStringAsync();
var model = JsonSerializer.Deserialize<Mobile>(result);

c # send parameters when sending json get request

I'm working on an application to make api get, post, delete, update requests on c # windowsforms.
My problem is: I want to send a parameter in "Body" when requesting a get. How can I do that ?
using System.Net.Http;
using System;
using System.Threading.Tasks;
using HastaTakip.Models;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Text;
namespace HastaTakip.Api
{
public class CustomersRepository
{
public HttpClient _client;
public HttpResponseMessage _response;
public HttpRequestMessage _requestMessage;
public CustomersRepository()
{
_client = new HttpClient();
_client.BaseAddress = new Uri("http://localhost:3000/");
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImZ0aG1seW16QGhvdG1haWwuY29tIiwidXNlcklkIjoxLCJpYXQiOjE2MTM5MDY5NDMsImV4cCI6MTYxNDA3OTc0M30.NER1RMTYx41OsF26pjiMXY-pLZTE-pIg4Q73ehwGIhA");
_client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<CustomersModel> GetList()
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("business_code", "dental")
});
_response = await _client.GetAsync(content);
var json = await _response.Content.ReadAsStringAsync();
var listCS = CustomersModel.FromJson(json);
return listCS;
}
}
}
to send a GET request with a JSON body:
HttpClient client = ...
...
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("some url"),
Content = new StringContent("some json", Encoding.UTF8, ContentType.Json),
};
var response = await client.SendAsync(request).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
But HTTP GET with a body is a somewhat unconventional construct that falls in a gray area of the HTTP specification!
You better create a class for your content data:
public class RequestData
{
pubic string BusinessCode {get; set;}
{
After this you can create your content object
public async Task<CustomersModel> GetList()
{
var data=new RequestData{BusinessCode="dental"}
var stringData = JsonConvert.SerializeObject(data);
contentData = new StringContent(stringData, Encoding.UTF8, "application/json");
var response = await _client.GetAsync(contentData);
// but I am not sure that Get will work correctly so I recommend to use
var response = await _client.PostAsync(contentData);
if (response.IsSuccessStatusCode)
{
var stringData = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<CustomersModel>(stringData);
}
else
{
....error code
}
}

Why do I get "not_authed"-error from Slack when sending a post-request from c#?

I am trying to serialize an object into Json and then send it to Slack. I have done this successfully without serializing but instead using "Dictionary" and "FormUrlEncodedContent" and then send it.
But now, for the purpose of making things easier and more agile, I just wanted to create one JSon-class which I could serialize and then use for every request I want to send.
Here is my code:
My JsonObject:
public class JsonObject
{
private string _token = "xoxp-MyToken";
[JsonProperty("token")]
public string token { get { return _token; } }
[JsonProperty("channel")]
public string channel { get; set; }
[JsonProperty("as_user")]
public bool as_user = true;
[JsonProperty("username")]
public string username { get;set; }
[JsonProperty("text")]
public string text { get; set; }
}
My client:
public class BpsHttpClient
{
private readonly HttpClient _httpClient = new HttpClient { };
public Uri UriMethod { get; set; }
public BpsHttpClient(string webhookUrl)
{
UriMethod = new Uri(webhookUrl);
}
public async Task<HttpResponseMessage> UploadFileAsync(StringContent requestContent)
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, UriMethod);
request.Content = requestContent;
var response = await _httpClient.SendAsync(request);
return response;
}
}
Main:
class MainArea
{
public static void Main( string[] args)
{
try
{
Task.WaitAll(SendMessage());
}
catch(Exception ass)
{
Console.WriteLine(ass);
Console.ReadKey();
}
}
private static async Task SendMessage()
{
var client = new BpsHttpClient("https://slack.com/api/chat.postMessage");
JsonObject JO = new JsonObject();
JO.channel = "DCW21NBHD";
JO.text = "This is so much fun :D !";
var Json = JsonConvert.SerializeObject(JO, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var StringJson = new StringContent(Json, Encoding.UTF8, "application/json");
var DeSon = JsonConvert.DeserializeObject(Json);
Console.WriteLine(DeSon); //this is for me to see if my JsonObject looks correct - it does ;)
Console.ReadKey();
var Response = await client.UploadFileAsync(StringJson);
string AnswerContent = await Response.Content.ReadAsStringAsync();
Console.WriteLine(AnswerContent);
Console.ReadKey();
}
}
When I run the code I allways get the answer:
Output:
{"ok":false,"error":"not_authed"}
although I think my JsonObject looks right - it has the token in there...
Anybody have an idea why?
So, i figured it out - I SHALL NOT put my token in the JsonObject I want to send.
The solution in this case (using httpclient) is that one has to add a header for authorization to the client, like so:
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "lé token");
and then it works.

ASP.Net Web API Returning Array Values

Pretty new with ASP.Net WEB API. Having some issues with the proper API configuration (and return type) for my API call which calls another ASHX service.
I have the following codes (tested in HomeController just to verify that the service call would work):
public async Task<ActionResult> Index()
{
WebRequest request = WebRequest.CreateHttp("http://callme/address.ashx");
var response = await request.GetResponseAsync();
string content;
using (var stream = response.GetResponseStream())
using(var reader = new StreamReader(stream))
{
content = await reader.ReadToEndAsync();
}
var result = JsonConvert.DeserializeObject<MyResult[]>(content);
return this.View();
}
public class MyResult
{
public string ClientAddress { get; set; }
}
Now, trying to port it over to an ASP.Net WEB API call:
ClientAddressController.cs
public class ClientAddressController: ApiController
{
public async IQueryable<MyResult> GetClientAddress()
{
WebRequest request = WebRequest.CreateHttp("http://callme/address.ashx");
var response = await request.GetResponseAsync();
string content;
using (var stream = response.GetResponseStream())
using(var reader = new StreamReader(stream))
{
content = await reader.ReadToEndAsync();
}
var result = JsonConvert.DeserializeObject<MyResult[]>(content);
// How to return the result object??
}
}
public class MyResult
{
public string ClientAddress { get; set; }
}
I need some help to properly define the correct parameters for the WEB Api call so that I could return the result object.
The result object would just be an array of strings:
[{"Address": "Address 100"}, {"Address": "Address 200"}, {"Address": "300"}]
Hoping to get some insights on resolving this. I have some idea with regards to returning database queries in Web API, but the service calls (and the async method) kind of threw me off the groove.
Thanks.
**UPDATE*****
Was able to find some resolution on this and I am posting the solution I have.
public class ClientAddressController: ApiController
{
public async Task<IHttpActionResult> GetClientAddress()
{
WebRequest request = WebRequest.CreateHttp("http://callme/address.ashx");
var response = await request.GetResponseAsync();
string content;
using (var stream = response.GetResponseStream())
using(var reader = new StreamReader(stream))
{
content = await reader.ReadToEndAsync();
}
var result = JsonConvert.DeserializeObject<MyResult[]>(content);
return Ok(result);
// How to return the result object??
}
}
public class MyResult
{
public string ClientAddress { get; set; }
}
P.S.: I am going to accept #Stripling's answer as his provided me some direction.
You'll need to create a class with an Address property, and map the results to objects of that class:
public async IQueryable<ClientAddressResult> GetClientAddress()
{
WebRequest request = WebRequest.CreateHttp("http://callme/address.ashx");
var response = await request.GetResponseAsync();
string content;
using (var stream = response.GetResponseStream())
using(var reader = new StreamReader(stream))
{
content = await reader.ReadToEndAsync();
}
IEnumerable<MyResult> result = JsonConvert.DeserializeObject<MyResult[]>(content);
return result.Select(r => new ClientAddressResult{Address = r.ClientAddress})
.AsQueryable();
}
DTO Classes:
public class MyResult
{
public string ClientAddress { get; set; }
}
public class ClientAddressResult
{
public string Address { get; set; }
}
You can return array values as dynamic List to be able to do that set method return with dynamic List.
var resultList = new List<dynamic>();
resultList.Add(new {Address="Address 100"});
resultList.Add(new {Address="Address 200"});
resultList.Add(new {Address="Address 300"});
return resultList;
Hope this is what you are loooking for.

Categories

Resources