Posting array value's to json API with C# - c#

i'm trying to send a post request to an online API to recieve net data, it was succesfull with normal key-value's but not with array's as value and i could't find it on the internet without creating a big amount of extra classes.
This is how i tried to post to the url with normal data (the 3th one needs an array in stead of a single object).
IEnumerable<KeyValuePair<string, string>> queries = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("keyA","ValueA"),
new KeyValuePair<string, string>("keyB", ""),
new KeyValuePair<string, string>("KeyC", "ValueCDE"), //array
};
HttpContent q = new FormUrlEncodedContent(queries);
Console.WriteLine(q.ToString());
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.PostAsync(url, q))
{
using (HttpContent content = response.Content)
{
string mycontent = await content.ReadAsStringAsync();
HttpContentHeaders headers = content.Headers;
Console.WriteLine(mycontent);
Console.WriteLine(response);
}
}
}
I tried to send raw data to the url but i recieved no response from it.
async static void PostRawRequest(string url)
{
string rawr = #"{
""a"":""a"",
""b"":"""",
""c"": [""C"", ""D"",""F""],
""StickerColor"": ""red""
}";
string result = "";
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
result = client.UploadString(url, "POST", rawr);
}
Console.WriteLine(result);
}
Can anyone help me in either the first(sending array values) or second (sending raw data)?

If you can, use a library to handle the serialization for you. Then you can do something like this (using Newtonsoft.Json):
using (var client = new HttpClient())
{
var json = JsonConvert.SerializeObject(yourObject);
client.PostAsync(yourUri, new StringContent(json, Encoding.UTF8, "application/json"));
}

Related

C# Converting string to JSON

I am trying to POST to using C# to a JSON payload which I can achieve but I am having trouble understanding how to replace the sample string with my own string.
From the code below you can see I have a string I want to send to my weblink. The code runs fine when I use "{\"text\":\"Hello, World!\"}" for the StringContent but if I try to replace it with the string of output_message it doesn't work. I am trying to work out how I convert my output_message to a format that JSON can recognize.
{
string output_message = "The file " + filename + " has been modified by " + user_modified + " and moved to the " + file_state + " file state. Please review the " + filename + " file and approve or reject.";
PostWebHookAsync(output_message);
Console.ReadLine();
}
static async void PostWebHookAsync(string Aoutput_message)
{
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "www.mywebsitelink"))
{
//request.Content = new StringContent("{\"text\":\"Hello, World!\"}", Encoding.UTF8, "application/json"); // - original do not delete
request.Content = new StringContent(Aoutput_message, Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(request);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
}
}
}
I want to replace "{\"text\":\"Hello, World!\"}" with a string
To the best of my knowledge people are moving away from JavaScriptSerializer and towards Json.NET. It's even recommended in the documentation here
The corresponding Json.NET code would look something like:
static async void PostWebHookAsync(string output_message)
{
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "www.mywebsitelink"))
{
string jsonValue = JsonConvert.SerializeObject(new
{
text = output_message
});
request.Content = new StringContent(jsonValue, Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(request);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
}
}
}
To use Json.NET you need to install the Newtonsoft.Json nuget package.
The best way is to create an object and serialize it.
To use JavaScriptSerializer you have to add a reference to System.Web.Extensions.dll
So for your problem, we create an anonymous object with a property text we pass the value Aoutput_message
static async void PostWebHookAsync(string Aoutput_message)
{
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "www.mywebsitelink"))
{
//request.Content = new StringContent("{\"text\":\"Hello, World!\"}", Encoding.UTF8, "application/json"); // - original do not delete
string jsonValue = new JavaScriptSerializer().Serialize(new
{
text = Aoutput_message,
});
request.Content = new StringContent(jsonValue, Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(request);
Console.WriteLine(response.StatusCode);
Console.WriteLine(response.Content);
}
}
}
Examples

Formatting RestSharp request for ESRI geocoder

I have some code that formats a JSON request using RestSharp to access ESRI geocoding API. The code works, but I'm wondering if there is a better way to get the request into the correct format here is a sample of what I have and below a sample of what the request should look like.
request = new RestRequest("geocodeAddresses", Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
//Format the request properly
var attributes = new Dictionary<string, object>();
attributes.Add("OBJECTID", address.Address);
attributes.Add("Address", address.Address);
attributes.Add("City", address.City);
attributes.Add("Region", address.State);
attributes.Add("Postal", address.ZipCode);
JsonObject attributesObj = new JsonObject();
foreach (var parms in attributes)
{
attributesObj.Add(parms);
}
JsonObject recordsObj = new JsonObject();
recordsObj.Add("attributes", attributesObj);
JsonArray EsriRequest = new JsonArray();
EsriRequest.Add(recordsObj);
JsonObject addressObj = new JsonObject();
addressObj.Add("records", EsriRequest);
request.AddParameter("addresses",
addressObj.ToString());
request.AddParameter("token", esriToken.ToString());
request.AddParameter("f", "json");
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
IRestResponse<EsriAddress> responseData = client.Execute<EsriAddress>(request);
Request output sample:
http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/geocodeAddresses?addresses={"records":[{"attributes":{"OBJECTID":1,"Address":"380 New York St.","City":"Redlands","Region":"CA","Postal":"92373"}},{"attributes":{"OBJECTID":2,"Address":"1 World Way","City":"Los Angeles","Region":"CA","Postal":"90045"}}]}&sourceCountry=USA&token=<YOUR TOKEN>&f=pjson
I currently only ever send one address, but in theory the api can take more then one at a time.
Here's how I send a batch of addresses to the geocodeAddresses method in the ArcGIS REST API. I'm not using RestSharp, just HttpClient:
string token = GetToken();
string url = "http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/geocodeAddresses";
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
var values = new[]
{
new KeyValuePair<string, string>("token", token),
new KeyValuePair<string, string>("forStorage", "true"),
new KeyValuePair<string, string>("MaxBatchSize", "1000"),
new KeyValuePair<string, string>("outFields", "*"),
new KeyValuePair<string, string>("f", "json"),
new KeyValuePair<string, string>("addresses", inputJson) // json string containing an array of a complex type
};
foreach (var keyValuePair in values)
content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
var response = await client.PostAsync(url, content);
Task<string> responseString = response.Content.ReadAsStringAsync();
string outputJson = await responseString;
}
}

Supplying api key in HttpClient's headers not working

I'm trying to get data from https://ndb.nal.usda.gov, basing on instructions provided here https://ndb.nal.usda.gov/ndb/doc/apilist/API-FOOD-REPORT.md
I'm using HttpClient as follows, but can't seem to be able to pass the api_key correctly. Shouldn't I be adding it to headers? I tried
public static async Task<string> DownloadItemData(string itemName)
{
using (HttpClient client = new HttpClient())
{
HttpContent requestContent =
new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("api_key", "myKey"),
new KeyValuePair<string, string>("ndbno", "01009"),
new KeyValuePair<string, string>("type", "f")
});
requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await client.PostAsync("http://api.nal.usda.gov/ndb/reports", requestContent);
using (StreamReader reader = new StreamReader(await response.Content.ReadAsStreamAsync()))
{
// Write the output.
string result = await reader.ReadToEndAsync();
return result;
}
}
But all I'm getting is:
{
"error": {
"code": "API_KEY_MISSING",
"message": "No api_key was supplied. Get one at http://api.nal.usda.gov"
}
}
I also tried this, but with the same result:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("api_key", "myKey");
Any ideas how to pass the api_key correctly? Thanks in advance!

Post Method in Windows Phone 8

I need to send some parameters to a php server using post method in WP8 app and get response in json format. I've tried everything that I found on stackoverflow and other sites, still could not.
The last code piece I come up with is:
public static async void GetData(string url, string data)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(new Uri(url), new StringContent(data));
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
MessageBox.Show(responseBody); // just showing the response for now
}
It shows a message from the server (which is an error stating some fields are missing) that it actually communicates with the server but the problem is with sending data. I call the above method like:
GetData("http_address_here", "?action=REGISTER&email=asc#fsdf.com&password=54561wefwe&firstname=sdfsdf&lastname=sdfsdf&picture=10");
But I saw an example sending data in xml. Possibly the mistake is about calling the method. Having seen tens of sample codes and trying everything, I really got confused about it. Any help is appreciated.
I finally managed to solve the problem. Thanks everyone for helping. The working code is below, it uses POST method and the resulting json object is stored as a string.
var values = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("email", "qewfwef"),
new KeyValuePair<string, string>("password", "qewfwef"),
new KeyValuePair<string, string>("firstname", "qewfwef"),
new KeyValuePair<string, string>("lastname", "qewfwef"),
new KeyValuePair<string, string>("picture", "123456")
};
var httpClient = new HttpClient(new HttpClientHandler());
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(values));
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
MessageBox.Show(responseString.ToString()); // just to see what we get
Can you try this
public static async Task<string> SendRequestPostResponse()
{
try
{
var postRequest = (HttpWebRequest)WebRequest.Create("your Url Here");
postRequest.ContentType = "application/x-www-form-urlencoded"; // Whichever content type you want to POST
postRequest.Method = "POST";
using (var requestStream = await postRequest.GetRequestStreamAsync())
{
byte[] postDataArray = Encoding.UTF8.GetBytes("your data here"); // Data for the POST request here
await requestStream.WriteAsync(postDataArray, 0, postDataArray.Length);
}
WebResponse postResponse = await postRequest.GetResponseAsync();
if (postResponse != null)
{
var postResponseStream = postResponse.GetResponseStream();
var postStreamReader = new StreamReader(postResponseStream);
string response = await postStreamReader.ReadToEndAsync();
return response;
}
return null;
}
}
HTTPWebRequest would be another alternative.

Troubleshooting HTTPClient asynchronous POST and reading results

I have a problem post string to form and read. Problem is they get away but need to do so sophisticated and it was very fast. Absolutely perfect multithreaded or asynchronous. Thank you very for your help.
This is my code.
private static void AsyncDown()
{
const string url = "http://whois.sk-nic.sk/index.jsp";
const string req = "PREM-0001";
var client = new HttpClient();
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("text", "PREM-0001")
};
FormUrlEncodedContent content = new FormUrlEncodedContent(pairs);
HttpResponseMessage response = client.PostAsync("http://whois.sk-nic.sk/index.jsp", content).Result;
if (response.IsSuccessStatusCode)
{
HttpContent stream = response.Content;
Task<string> data = stream.ReadAsStringAsync();
}
}
Taking a rough stab in the dark at what your problem is, I'd guess that you're having trouble reading the response of your call.
When the content is POSTed to the server,
HttpResponseMessage response
= client.PostAsync("http://whois.sk-nic.sk/index.jsp", content).Result;
if (response.IsSuccessStatusCode)
{
HttpContent stream = response.Content;
Task<string> data = stream.ReadAsStringAsync();
}
It does so asynchronously, so the code will continue execution even though the result is not (most likely) available yet. Checking response.IsSuccessStatusCode will thus not give you the behavior you're expecting.
Change your calls to look like this by adding the await keyword:
HttpResponseMessage response
= await client.PostAsync("http://whois.sk-nic.sk/index.jsp", content);
Then, change the reading of the stream to use await as well:
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
}
EDIT: got some await objects mixed up and have corrected the code listing.
edit 2: here is the complete LINQPad script that I used to successfully download an HTML page from the given URL.
var client = new HttpClient();
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("text", "PREM-0001")
};
FormUrlEncodedContent content = new FormUrlEncodedContent(pairs);
HttpResponseMessage response = await client.PostAsync("http://whois.sk-nic.sk/index.jsp", content);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
//data.Dump(); //uncomment previous if using LINQPad
}
Maybe the site has changed since last post but now the request parameter name is whois not text. If this was the case a year ago too that's why it didn't work.
Today site responds to get too, i.e. http://whois.sk-nic.sk/index.jsp?whois=PREM-0001
Full code with get:
private async Task<string> Get(string code)
{
using (var client = new HttpClient())
{
var requestUri = String.Format("http://whois.sk-nic.sk/index.jsp?whois={0}", code);
var data = await client.GetStringAsync(requestUri);
return data;
}
}
Full code with post:
private async Task<string> Post()
{
using (var client = new HttpClient())
{
var postData = new KeyValuePair<string, string>[]
{
new KeyValuePair<string, string>("whois", "PREM-0001"),
};
var content = new FormUrlEncodedContent(postData);
var response = await client.PostAsync("http://whois.sk-nic.sk/index.jsp", content);
if (!response.IsSuccessStatusCode)
{
var message = String.Format("Server returned HTTP error {0}: {1}.", (int)response.StatusCode, response.ReasonPhrase);
throw new InvalidOperationException(message);
}
var data = await response.Content.ReadAsStringAsync();
return data;
}
}
Or a parser could be used because I guess extracting the returned values is the final goal:
private void HtmlAgilityPack(string code)
{
var requestUri = String.Format("http://whois.sk-nic.sk/index.jsp?whois={0}", code);
var request = new HtmlWeb();
var htmlDocument = request.Load(requestUri);
var name = htmlDocument.DocumentNode.SelectSingleNode("/html/body/table[1]/tr[5]/td/table/tr[2]/td[2]").InnerText.Trim();
var organizations = htmlDocument.DocumentNode.SelectSingleNode("/html/body/table[1]/tr[5]/td/table/tr[3]/td[2]").InnerText.Trim();
}

Categories