Best efficient way of converting JSON string to model object - c#

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);

Related

How to handle multiple http requests using single instance of HttpClient?

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?

PostAsync API giving Bad Gateway

I am invoking a third party POST API from my own API (again POST METHOD). The third party API is having a security key, and it is working fine on the POSTMAN tool. However, when I tries to invoke through code, I am getting error, 'Bad Gateway'. Following is the code which I tried.
public static async Task<string> GetDetailsfromThirdParty(string kszstrng)
{
string contentstring = string.Empty;
using (var client = new HttpClient())
{
string baseURL = "https://abcde.kz.in/b2/vhsearch-all";
string prms = kszstrng;// input parameters to API, in JSON Format- this is JSON String.
try
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Add("key", "value");
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(prms);
var content = new ByteArrayContent(messageBytes);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var response = await httpClient.PostAsync(baseURL, content).ConfigureAwait(false);
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
contentstring = result;
}
}
catch (Exception ex)
{
string msg = ex.Message.ToString();
}
return contentstring;
}
}
I am getting error on this line:
var response = await httpClient.PostAsync(baseURL, content).ConfigureAwait(false);
While trying to execute I am getting the below error:
Not able to find out what's the issue? There is no network / Fireawall blockage. I have cross-verified with Systems Team as well.
Please suggest any issue with the code.
First of all, i recommend you to not declare the HttpClient in a using statement since this can cause a socket exhaustion (because the connections will stay open).
(see the docs for details)
Go for a static HttpClient (or use the IHttpClientFactory if you're project is .net Core).
I can't test your code since I'm not able to access this api.
But give it a try using a cleaner approach:
// static HttpClient
private static readonly HttpClient _HttpClient = new HttpClient();
// Can be used to set the baseUrl of the HttpClient from outside
public static void SetBaseUrl(Uri baseUrl)
{
_HttpClient.BaseAddress = baseUrl;
}
public static async Task<string> GetDetailsfromThirdParty(string kszstrng)
{
string contentstring = string.Empty;
string baseURL = "https://abcde.kz.in/b2/vhsearch-all";
string prms = kszstrng; // input parameters to API, in JSON Format- this is JSON String.
try
{
// Be aware of which headers you wanna clean if using the static HttpClient
_HttpClient.DefaultRequestHeaders.Accept.Clear();
_HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_HttpClient.DefaultRequestHeaders.Add("key", "value");
_HttpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
byte[] messageBytes = Encoding.UTF8.GetBytes(prms);
var content = new ByteArrayContent(messageBytes);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await _HttpClient.PostAsync(baseURL, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
contentstring = result;
}
}
catch (Exception ex)
{
// your exception handling
}
return contentstring;
}
Issue resolved. While forming the object to JSON String, there was an opening and closing angle brackets ([,]). Even though this is coming automatically while converting to JSON string, this was not accepted string at the vendor end. So I removed it and works perfectly. Thanks every one for the support.

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

How to use HttpClient to get non-primitive types in MVC 6

I have the following WebAPI client code in an MVC 6 project:
public async Task<Blog> GetData()
{
Blog result = null;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:55792/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// New code:
HttpResponseMessage response = await client.GetAsync("api/values/1");
if (response.IsSuccessStatusCode)
{
result = await response.Content.???;
return result;
}
}
return result;
}
I can't use it, as the DNX core does not support WebAPI.Client NuGet package (which contains ReadAsync<MyClass>()) so I have to use System.Net.Http.
It has only 3 reading functions:
ReadAsByteArrayAsync
ReadAsStreamAsync
ReadAsStringAsync
None of them can read an arbitrary typed object.
What should I use now?
You can deserialize the JSON, Newtonsoft is one popular library:
...
string payload = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<MyClass>(payload);
...
Not tested code, but completed code here with download option
public ActionResult Part2()
{
List<Employee> list = new List<Employee>();
HttpClient client = new HttpClient();
var result = client.GetAsync("http://localhost:1963/api/Example").Result;
if (result.IsSuccessStatusCode)
{
list = result.Content.ReadAsAsync<List<Employee>>().Result;
}
return View(list);
}

Receiving JSON data back from HTTP request

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;

Categories