How to check if i properly parsed through the JSON? - c#

This is my first time calling an API and parsing through the JSON output. I know I called the API and retrieved the data since I printed it onto the console but I now want to print out a certain part of the JSON for example: all the titles of the list (if it had titles and some other information).
public async Task MainAsync()
{
using (var client = new HttpClient()) //creates a new client that will make the call to the api.
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); // Accepts header for JSON format
try
{
HttpResponseMessage response = await client.GetAsync("http://quickstats.nass.usda.gov/api/api_GET/?key=MYKEYGOESHERE&commodity_desc=CORN&year__GE=2012&state_alpha=VA&format=JSON");
if (response.IsSuccessStatusCode)
{
string contents = await response.Content.ReadAsStringAsync();
Console.WriteLine(contents);
//List<quickStats> quickStat = JsonConvert.DeserializeObject<List<quickStats>>(contents);
quickStats quickStat = JsonConvert.DeserializeObject<quickStats>(contents);
Console.WriteLine("Done");
foreach(var item in quickStat)
{
Console.WriteLine(item.source_desc);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//Console.WriteLine("test");
}
}
}
}
class quickStats
{
public String source_desc { get; set; }
}
The JSON isn't in an array so I can't create a list like in the commented line then do a foreach statement for that list, following this vid: https://www.youtube.com/watch?v=xkB-cIMjXGQ
I am wondering how else I can print the parsed list of "source_desc".
Any help is appreciated!

It's structure like this
{"data":[
{"source_desc": "XXXX"},
{"source_desc": "OOOO"},
{"source_desc": "TTTT"}
]}
so your serialization class should be defined as:
class quickStats
{
public List<quickStatsDetail> data { get; set; }
}
class quickStatsDetail
{
public String source_desc { get; set; }
}

Related

How to convert Object and view it on WebAPI?

Here is my question,
I got a Web API and client(winform), client will send out data with a Serialize Object. My Web API do have received and return a response to client. But I can't view the data on Web API, I do have try using Deserialize Object and convert it into string but not working neither.
Please help me,Thanks!
Here is my code:
Client
private string WebApiPost(string sParam, string sJson)
{
var client = new HttpClient();
var content = new StringContent(sJson, Encoding.UTF8, "application/json");
var response = client.PostAsync(sWebAPI_URL + sParam, content).Result;
var body = response.Content.ReadAsStringAsync().Result;
return body;
}
This is my Web API
public object Post([FromBody]object hL7)
{
//what should I do???
//I've tried set hL7 into string but it wont get any data;
//I've also tried deserialize it but will get 500 internal server error.
return hL7;
}
This is my WebAPI model
public class HL7MID
{
public string LOC { get; set; }
public string COMPANY { get; set; }
}
public class HL7MID_List
{
public string sMSG { get; set; }
public List<HL7MID> data = new List<HL7MID>();
}
Because sJson matches HL7MID, you can use that type in as a paramter of your Post function, and just use that type.
public HL7MID Post([FromBody]HL7MID hL7)
{
//use hL7 here
return hL7;//also since you know the return type, changing that to HL7MID is suggested
}

How to Seriailize an c# object into Json, while using httpClient?

I have a little program which should communicate with "Slack". In an older Version I used "Dictionary<string, string>" and then put them into UrlEncodedContent - which worked fine.
Now I am trying to create a Json-object, using Newtonsoft's Nuget-package and (in my opinion) formatting my object the way they say on their website.
Problem is, when I try to make a simple request, my program just runs to one specific line in the code(var response = await _httpClient.SendAsync(request);) and then it just ends. It doesn't throw an exception or display any kind of message, it simply ends on this line. I went through my code step by step while debugging, that's how I know it ends on exactly this line. And I just don't know why!
Now my code:
First, my object...
namespace BPS.Slack
{
public class JsonObject
{
//generally needed parameters
[JsonProperty("ok")]
public bool ok { get; set; }
[JsonProperty("error")]
public string error { get; set; }
[JsonProperty("channel")]
public string channel { get; set; }
[JsonProperty("token")]
private string token = "xoxp-MyToken";
[JsonProperty("as_user")]
public bool as_user = false;
[JsonProperty("username")]
public string username { get;set; }
//--------------------------------
//only needed for textmessages
[JsonProperty("text")]
public string text { get; set; }
//--------------------------------
//for posting messages with data attached
[JsonProperty("initial_comment")]
public string initial_comment { get; set; }
[JsonProperty("file")]
public string file { get; set; }
[JsonProperty("channels")]
public string channels { get; set; }
//--------------------------------
//for getting the latest message from a channel
[JsonProperty("count")]
public string count = "1";
[JsonProperty("unreads")]
public bool unreads = true;
}
}
now the client:
namespace BPS.Slack
{
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(MultipartFormDataContent requestContent)
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, UriMethod);
request.Content = requestContent;
var response = await _httpClient.SendAsync(request);
return response;
}
}
}
and the main
namespace TestArea
{
class MainArea
{
public static void Main( string[] args)
{
try
{
Task.WhenAll(SendMessage());
}
catch(Exception ass)
{
Console.WriteLine(ass);
Console.ReadKey();
}
}
private static async Task SendMessage()
{
var client = new BpsHttpClient("https://slack.com/api/im.history");
JsonObject JO = new JsonObject();
JO.channel = "DCW21NBHD";
var Json = JsonConvert.SerializeObject(JO);
var StringJson = new StringContent(Json, Encoding.UTF8);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(StringJson);
var Response = await client.UploadFileAsync(content);
string AnswerContent = await Response.Content.ReadAsStringAsync();
Console.WriteLine(AnswerContent);
Console.ReadKey();
}
}
}
I had the same problem in my older version, BUT only as I wanted to DEserialize an answer I got from Slack. It had to do with my object I tried do deserialize the answer into. But this time I can not figure out what's wrong. But, as I said, I do not have any experience with using serialized objects as Json-property to send requests... anyone has an idea what is wrong with my code?
EDIT: This problem is kinda solved. But there is a follow up problem.
Okay, I found out that the reason for the abprubt termination was the
Task.WhenAll(SendMessage());
it should be
Task.WaitAll(SendMessage()); Why??? Somebody said I should use WhenAll, but obviously it doesn't work properly in this case...
Now I get a response from Slack, but now a different problem has arisen. When I use this method:
public async Task<HttpResponseMessage> UploadFileAsync(MultipartFormDataContent requestContent)
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, UriMethod);
request.Content = requestContent;
var response = await _httpClient.SendAsync(request);
return response;
}
I allways get the answer:
{"ok":false,"error":"invalid_form_data"}
so I tried to explicitly tell it the 'mediaType', I tried "application/json" and others, but with all of them I get the same error. Here is the full method that calls the upper mehtod:
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 requestContent = new MultipartFormDataContent();
requestContent.Add(StringJson);
var Response = await client.UploadFileAsync(requestContent);
string AnswerContent = await Response.Content.ReadAsStringAsync();
}
When I use this method:
public async Task<HttpResponseMessage> SendMessageAsync(FormUrlEncodedContent content)
{
var response = await _httpClient.PostAsync(UriMethod, content);
return response;
}
so bascially I am passing "FormUrlEncodedContent" instead of "MultipartFormDataContent" in this, and then I get the response I want and can work wiht it. BUT this i of little use to me since I have to use "MultipartFormDataContent" to be able to send files with my requests.
Anyone have an idea what is failing here? Why does it not like the one content-type but the other one? I'd be gratefull for tipps and ideas!
You are serializing your object to Json and then adding it to a Multipart body, that's quite strange. Unless you're uploading binary data (eg Files), there is no need to use MultipartFormDataContent.
You are can directly post your JsonObject serialized as JSON:
public async Task<HttpResponseMessage> PostJsonAsync(StringContent content)
{
var response = await client.PostAsync(url, content);
return response;
}
var client = new BpsHttpClient("https://slack.com/api/im.history");
JsonObject JO = new JsonObject();
JO.channel = "DCW21NBHD";
var Json = JsonConvert.SerializeObject(JO);
var StringJson = new StringContent(Json, Encoding.UTF8);
var Response = await client.PostJsonAsync(content);
Also this is should be POST on the UploadFileAsync function.
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, UriMethod);
so I figured out that in the Main() the problem was this:
Task.WhenAll(SendMessage());
I should instead use:
Task.WaitAll(SendMessage());
Anyone who has more knowledge on this, please elaborate why!

Post Method HTTP response is 200 but no data changed In web api

I want to post data form my code but no data changed . when I debug the code it got me 200 which mean code is good . I tried to test in fiddler and data is changed successfully . I want to know where is the wrong ?
this is my service including url
public static async Task<string> PostOrderAsync(MachinePostModel Order)
{
try
{
var client = new HttpClient();
string data = JsonConvert.SerializeObject(Order);
var content = new StringContent(data, Encoding.UTF8, "application/json");
var response = await client.PostAsync("http://94.205.253.150:2016/api/JobOrder", content);
return data;
}
catch
{
return null;
}
}
and this is the step where i send order object
private async Task<bool> AcceptPostOrder()
{
MachinePostModel OrderDetails = new MachinePostModel();
try
{
OrderDetails.ID = 1163;
OrderDetails.joStatus = "should to wait";
OrderDetails.remarks = "hello remarks";
var Client = await Services.MachineTestPostService.PostOrderAsync(OrderDetails);
return true;
}
catch (Exception exc)
{
await MachineTestOrderView.machineobj.DisplayAlert("Alert", exc.Message, "OK");
return false;
}
}
finally my model
public class MachinePostModel
{
public int ID { get; set; }
public string remarks { get; set; }
public string joStatus { get; set; }
}
Get link to check if data is changed
http://94.205.253.150:2016/api/JobOrder/Get?regId=1&driverID=35&status=All%20Status
There are some mistakes in your code. Firstly, decorate your action with HttpPost attribute and add a parameter for sent complex object.
[HttpPost]
private async Task<bool> AcceptPostOrder(MachinePostModel Order)
{
MachinePostModel OrderDetails = new MachinePostModel();
try
{
OrderDetails.ID = 1163;
OrderDetails.joStatus = "should to wait";
OrderDetails.remarks = "hello remarks";
var Client = await Services.MachineTestPostService.PostOrderAsync(OrderDetails);
return true;
}
catch (Exception exc)
{
await MachineTestOrderView.machineobj.DisplayAlert("Alert", exc.Message, "OK");
return false;
}
}
And, there is no routing definition as api/JobOrder, so I assume that you are trying to post the data AcceptPostOrder method. Change the request endpoint;
var response = await client.PostAsync("http://94.205.253.150:2016/api/AcceptPostOrder", content);

Calling C# await calls in a loop to retrieve JSON data from web

I have a method that calls an API with HttpClient and build a list of Customers as IEnumerable<Customer>. The way this API works is that it will return only 100 customers at a time, and will provide another link in the JSON content to fetch again the next 100.
How can I structure this code to iteratively fetch the records until all are fetched and build a large IEnumerable<Customer> and return from this method. It is okay to break this large method to another small one. I don't want a synchronous process.
Task<IEnumerable<Customer>> GetCustomers(string url)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
// TODO: Deserialize responseBody and build a new IEnumerable<Customer>
}
Json:
{
"nextRecords": "\\customers\\123",
"customers": [
{"name": "John Doe"},
{"name": "Mary Doe"}
]
}
From sample JSON the following models are derived.
public class RootObject {
public string nextRecords { get; set; }
public IList<Customer> customers { get; set; }
}
public class Customer {
public string name { get; set; }
}
Getting the result can be done using
HttpClient client = new HttpClient();
async Task<IEnumerable<Customer>> GetCustomers(string url) {
var result = new List<Customer>();
do {
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsAsync<RootObject>();
result.AddRange(body.customers);
url = body.nextRecords;
} while(!string.IsNullOrWhitespace(url));
return result;
}

Modify List<T> object to work with method that receives <T> or viceversa in C#

I need some suggestion on how to fix my code. I'm working on some existing project which has a bunch of dependencies, so the less I have to modify, the better. In this case, my controller needs BuildingReportModel as LIST, and at the end this controller returns this list to some view. My issue is when I try to call GetWSObject which receives a model/class, no a LIST. How would be the best way or best practices to make this code work? BuildingReportModel needs to be declare as List<> since I have some previous validation that can't be changed. Any suggestions?
List<BuildingReportModel> rc = new List<BuildingReportModel>();
BuildingWSObjects ws = new BuildingWSObjects();
rc = await ws.GetWSObject<BuildingReportModel>("all");
return View(rc);
public class BuildingReportModel
{
public string message1 { get; set; }
public string message2 { get; set; }
}
public class BuildingWSObjects
{
public async Task<T> GetWSObject<T>(string uriActionString)
{
T returnValue =
default(T);
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost/logger");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(uriActionString);
response.EnsureSuccessStatusCode();
returnValue = JsonConvert.DeserializeObject<T>(((HttpResponseMessage)response).Content.ReadAsStringAsync().Result);
}
return returnValue;
}
catch (Exception e)
{
throw (e);
}
}
}
I would modify BuildingWSObjects class and add new method:
public async Task<List<T>> GetWSObjects<T>(string uriActionString)
{
return new List<T> { await this.GetWSObject<T>(uriActionString)};
}
pass list to your GetWSObject than it will return you a list.
rc = await ws.GetWSObject<List<BuildingReportModel>>("all");

Categories