Im new to System.Net with C#
I want a way to get info from this website api: https://fn-api.glitch.me/api/aes
from its json to a C# string
I have this so far
I don't know how to get each item and where to put the url (im really new to this).
I want the url in a string:
public class Data
{
public string build { get; set; }
public string netCL { get; set; }
public string manifestID { get; set; }
public string aes { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
Okay, this is how you get about it. I am showing you an example using HttpClient to first read the content from the API and then de-serialize it using Newtonsoft package.
HttpClient class:
public class HttpClientFactory
{
private string webServiceUrl = "https://fn-api.glitch.me/";
public HttpClient CreateClient()
{
var client = new HttpClient();
SetupClientDefaults(client);
return client;
}
protected virtual void SetupClientDefaults(HttpClient client)
{
//This is global for all REST web service calls
client.Timeout = TimeSpan.FromSeconds(60);
client.BaseAddress = new Uri(webServiceUrl);
}
}
Your Model class:
public class Data
{
public string build { get; set; }
public string netCL { get; set; }
public string manifestID { get; set; }
public string aes { get; set; }
}
public class RootObject
{
public Data data { get; set; }
}
Now, you can call this class and create an instance of the HttpClient like this:
public RootObject InvokeAPI()
{
RootObject apiresponse = new RootObject();
string result = string.Empty;
HttpClientFactory clientFactory = new HttpClientFactory();
var client = clientFactory.CreateClient();
HttpResponseMessage response = client.GetAsync("api/aes").Result;
if (response.IsSuccessStatusCode)
{
result = response.Content.ReadAsStringAsync().Result;
apiresponse = JsonConvert.DeserializeObject<RootObject>(result);
}
return apiresponse;
}
Hope this helps you out.
EDIT:
As per your code, you need to call the API on your Button click:
private void metroButton2_Click_1(object sender, EventArgs e)
{
//You need to invoke the API method !!!!
var apiresponse=InvokeAPI();
metroTextBox1.Text = apiresponse.data.aes;
}
Be sure to put try-catch blocks on your code for error handling.
I'd recommend using a 3rd party library like RestSharp. It'll give you a client that's easy to work with and does the converting into objects automatically.
Alternatively you could use the WebClient and download the JSON. Using something like Json.NET allows you to deserialize the JSON into an object.
Easiest way to read from a URL into a string in .NET
I use JSON.Net.
Related
I am trying to send data from winform datagridview to webapi, so i convert datagridview to json. While sending json it failed to POST data and send this error:
'Failed to POST data: (BadRequest): {"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","title": "One or more validation errors occurred.","status":400,"traceId":"00-fb84f3c1c1802a481cbe7aba7ef73193-80be6fe9c57344d2-00","errors":{"$":["The JSON value could not be converted to LabDataApi.Models.LabData. Path: $ | LineNumber: 0 | BytePositionInLine: 421."]}}'
Codes:
public class LabData
{
public int SerialNumber { get; set; }
public string LabParameterName { get; set; }
public decimal LabValue { get; set; }
public DateTime LabDate { get; set; }
}
private void button2_Click(object sender, EventArgs e)
{
var url = "https://localhost:7248/api/Lab";
dataGridView1.DataSource = LabResult.GetLabData();
var table = JsonConvert.SerializeObject(dataGridView1.DataSource);
ApiSender apiSender = new ApiSender();
apiSender.POSTData(table, url);
}
public class ApiSender
{
private static HttpClient _httpClient = new HttpClient();
public bool POSTData(object json, string url)
{
using (var content = new StringContent(JsonConvert.SerializeObject(json), System.Text.Encoding.UTF8, "application/json"))
{
HttpResponseMessage result = _httpClient.PostAsync(url, content).Result;
if (result.StatusCode == System.Net.HttpStatusCode.Created)
return true;
string returnValue = result.Content.ReadAsStringAsync().Result;
throw new Exception($"Failed to POST data: ({result.StatusCode}): {returnValue}");
}
}
}
Receiving Json data format
[{"SerialNumber":1,"LabParameterName":"abc","LabValue":7.80,"LabDate":"2001-11-16T10:10:00"},{"SerialNumber":2,"LabParameterName":"xyz","LabValue":10.00,"LabDate":"2001-11-16T10:10:00"},{"SerialNumber":3,"LabParameterName":"qq","LabValue":5.00,"LabDate":"2001-03-16T10:10:00"},{"SerialNumber":18,"LabParameterName":"cbc","LabValue":200.0,"LabDate":"2001-11-16T10:10:00"}]
The JSON value could not be converted to LabDataApi.Models.LabData
Well, you are trying to convert an array of LabData into the LabData model. Update the API to receive IEnumerable<LabData>, or update the client to send multiple POST requests (for each LabData entry (not recommended)).
At least that's the answer to the question you've asked - it looks like you have cut off the end of the exception, perhaps you omitted some essential details by mistake?
There is an issue with your objects definitions when converting to json. Also, you'll want to get it as a List or an Array.
Your serialization/deserialization will work better with these objects.
public class LabDatas
{
public LabData[] Value { get; set; }
}
//or if you want list
public class LabDatas
{
public List<LabData> Value { get; set; }
}
public class LabData
{
public int SerialNumber { get; set; }
public string LabParameterName { get; set; }
public float LabValue { get; set; }
public DateTime LabDate { get; set; }
}
I'm new to c# and I have created a library that contain currency exchange rate from an API to a string
using System.Net;
namespace RateLib
{
public class CurrencyRate
{
public void getRate()
{
string url = "apikey";
WebClient myClient = new WebClient();
string txt = myClient.DownloadString(url);
}
}
}
Now, how I can put this txt string into a hashmap (if it does exist in c#) or a Dictionary ?
I think that what you want is to deserialize your json into a class containing a IDictionary for your rates. To do that we will use System.Text.Json's JsonSerializer.Deserialize.
Something like this:
public class Latest
{
public string Disclaimer { get; set; }
public string License { get; set; }
public int Timestamp { get; set; }
public string Base { get; set; }
public IDictionary<string, double> Rates { get; set; }
}
public static void Main()
{
var url = "https://openexchangerates.org/api/latest.json?app_id=69cb235f2fe74f03baeec270066587cf";
var myClient = new WebClient();
var json = myClient.DownloadString(url);
var options = new JsonSerializerOptions{PropertyNamingPolicy = JsonNamingPolicy.CamelCase};
var latest = JsonSerializer.Deserialize<Latest>(json, options);
Console.WriteLine(latest.Rates.First());
}
output
[AED, 3.6732]
Try it Online!
Last things, this apikey seems valid. You may want to change it now that it is exposed to the world.
I am making a simple WinForm Application in Windows and I want to get some data about foreign exchange rates. So I decided to call an API from Oanda. I tried several things around but nothing worked. It gives the response in CSV as well as JSON format. I don't know which will be easier to handle.
Also for this type of response, I am unable to create its model class.
Response:
JSON:
{
"meta": {
"effective_params": {
"data_set": "OANDA",
"base_currencies": [
"EUR"
],
"quote_currencies": [
"USD"
]
},
"endpoint": "spot",
"request_time": "2019-06-08T12:05:23+00:00",
"skipped_currency_pairs": []
},
"quotes": [
{
"base_currency": "EUR",
"quote_currency": "USD",
"bid": "1.13287",
"ask": "1.13384",
"midpoint": "1.13336"
}
]
}
CSV:
base_currency,quote_currency,bid,ask,midpoint
EUR,USD,1.13287,1.13384,1.13336
I just need those three numbers so, which method will be helpful and how.
This code I already tried:
var client = new HttpClient();
client.BaseAddress = new Uri("https://www1.oanda.com/rates/api/v2/rates/");
HttpResponseMessage response = await client.GetAsync("spot.csv?api_key=<myapikey>&base=EUR"e=USD");
string result = await response.Content.ReadAsStringAsync();
textBox1.Text = result;
Edit: I need the result of this call for my further processing so I must need this method to complete its execution before proceeding further
First creating model from Json:
use a online model generator like Json2C#, for the Json that you have posted, following is the model generated:
public class EffectiveParams
{
public string data_set { get; set; }
public List<string> base_currencies { get; set; }
public List<string> quote_currencies { get; set; }
}
public class Meta
{
public EffectiveParams effective_params { get; set; }
public string endpoint { get; set; }
public DateTime request_time { get; set; }
public List<object> skipped_currency_pairs { get; set; }
}
public class Quote
{
public string base_currency { get; set; }
public string quote_currency { get; set; }
public string bid { get; set; }
public string ask { get; set; }
public string midpoint { get; set; }
}
public class RootObject
{
public Meta meta { get; set; }
public List<Quote> quotes { get; set; }
}
Now connecting to the WebAPI using HttpClient, which has the option to return both Json and CSV, I would prefer JSON being standard, which can also be consumed easily by variety of clients, use the following simple generic methods:
Assuming it is GET only call, just supply the Host and API details to the generic Process method underneath:
public async Task<TResponse> Process<TResponse>(string host,string api)
{
// Execute Api call Async
var httpResponseMessage = await MakeApiCall(host,api);
// Process Json string result to fetch final deserialized model
return await FetchResult<TResponse>(httpResponseMessage);
}
public async Task<HttpResponseMessage> MakeApiCall(string host,string api)
{
// Create HttpClient
var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true }) { BaseAddress = new Uri(host) };
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Make an API call and receive HttpResponseMessage
HttpResponseMessage responseMessage = await client.GetAsync(api, HttpCompletionOption.ResponseContentRead);
return responseMessage;
}
public async Task<T> FetchResult<T>(HttpResponseMessage result)
{
if (result.IsSuccessStatusCode)
{
// Convert the HttpResponseMessage to string
var resultArray = await result.Content.ReadAsStringAsync();
// Json.Net Deserialization
var final = JsonConvert.DeserializeObject<T>(resultArray);
return final;
}
return default(T);
}
How to use:
Simply call:
var rootObj = await Process<RootObject>("https://www1.oanda.com/rates/", "api/v2/rates/");
You receive the deserialized RootObject as shown in the model above
For anything further complex processing like sending input to the call with http body, above generic code needs further modification, it is currently only specific to your requirement
Edit 1: (Making the entry call Synchronous)
To make the overall call synchronous, use the GetAwaiter().GetResult() at the topmost level, Main method will be converted to, rest all will remain same as in the sample (async methods)
void Main()
{
var rootObj = Process<RootObject>("https://www1.oanda.com/rates/", "api/v2/rates/").GetAwaiter().GetResult();
}
Edit 2: (Making complete code Synchronous)
void Main()
{
var rootObj = Process<RootObject>("https://www1.oanda.com/rates/", "api/v2/rates/");
}
public TResponse Process<TResponse>(string host, string api)
{
// Execute Api call
var httpResponseMessage = MakeApiCall(host, api);
// Process Json string result to fetch final deserialized model
return FetchResult<TResponse>(httpResponseMessage);
}
public HttpResponseMessage MakeApiCall(string host, string api)
{
// Create HttpClient
var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true }) { BaseAddress = new Uri(host) };
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Make an API call and receive HttpResponseMessage
HttpResponseMessage responseMessage = client.GetAsync(api, HttpCompletionOption.ResponseContentRead).GetAwaiter().GetResult();
return responseMessage;
}
public T FetchResult<T>(HttpResponseMessage result)
{
if (result.IsSuccessStatusCode)
{
// Convert the HttpResponseMessage to string
var resultArray = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
// Json.Net Deserialization
var final = JsonConvert.DeserializeObject<T>(resultArray);
return final;
}
return default(T);
}
You can use an online service such as json2csharp to get your json model and Json.Net to serialise and deserialise the json string. The following models your json.
public class EffectiveParams
{
public string data_set { get; set; }
public List<string> base_currencies { get; set; }
public List<string> quote_currencies { get; set; }
}
public class Meta
{
public EffectiveParams effective_params { get; set; }
public string endpoint { get; set; }
public DateTime request_time { get; set; }
public List<object> skipped_currency_pairs { get; set; }
}
public class Quote
{
public string base_currency { get; set; }
public string quote_currency { get; set; }
public string bid { get; set; }
public string ask { get; set; }
public string midpoint { get; set; }
}
public class RootObject
{
public Meta meta { get; set; }
public List<Quote> quotes { get; set; }
}
Note that you can change RootOject to a more descriptive name.
So, for example, to get the bid, ask and midpoint value for each quotes, you can simply do this:
RootObject rootObj=JsonConvert.DeserializeObject(jsonString);
//Get the required values.
foreach(var quote in rootObj.quotes)
{
Console.WriteLine($"Bid : {quote.bid} Ask: {quote.ask} MidPoint: {quote.midpoint}");
}
[Update: This question is different from the suggested duplicate because this one is about deserialization of XML and the explanation of the problem and solution on this one is clearer as I've included the full source code.]
I'm trying to read and subsequently manipulate a response from a Web API. Its response looks like this:
<MYAPI xsi:noNamespaceSchemaLocation="MYAPI.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MySite Resource="some resource name">
<Name>some name</Name>
<URL>some url</URL>
<SecondName>Describes something</SecondName>
</MySite>
... A lot of these <MySite>...</MySite> are there
<SomeOtherSite Resource="some resource name">
<Name>some name</Name>
<URL>some url</URL>
</SomeOtherSite>
</MYAPI>
SomeOtherSite is not repeating and only one of it appears at the end of the response. But the MySite is the one that is repeating.
I've modeled the class for this XML response as:
public class MYAPI
{
public List<MySite> MySite { get; set; }
public SomeOtherSite SomeOtherSite { get; set; }
}
public class MySite
{
public string Name { get; set; }
public string URL { get; set; }
public string SecondName { get; set; }
}
public class SomeOtherSite
{
public string Name { get; set; }
public string URL { get; set; }
}
And this is my code:
static void Main()
{
var handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential("MyUsername", "MyPassword");
var client = new HttpClient(handler);
client.BaseAddress = new Uri("https://sitename.com:PortNumber/");
var formatters = new List<MediaTypeFormatter>()
{
new XmlMediaTypeFormatter(){ UseXmlSerializer = true }
};
var myApi = new MYAPI();
HttpResponseMessage response = client.GetAsync("/api/mysites").Result;
if (response.IsSuccessStatusCode)
{
myApi = response.Content.ReadAsAsync<MYAPI>(formatters).Result;
}
}
Now the myApi only has object for SomeOtherSite but the list for the MySite is empty.
Would someone please tell me how I should deserialize this response correctly?
Should I be creating custom media formatter? I have no idea of it by the way.
Also would you please tell me how to model that Resource attribute coming in the response?
And I can't change anything in the WebAPI server. I just need to consume the data from it and use it elsewhere.
Thank You so much!
I solved this after some really good direction from: https://stackoverflow.com/users/1124565/amura-cxg Much Thanks!
The solution was to annotate all the properties with XMLAttributes. And it correctly deserialized the response. And as for the Resource attribute, all I needed was [XmlAttribute(AttributeName="Resource")]
The rest of the source code works as is.
[XmlRoot(ElementName="MYAPI")]
public class MYAPI
{
[XmlElement(ElementName="MySite")]
public List<MySite> MySite { get; set; }
[XmlElement(ElementName="SomeOtherSite")]
public SomeOtherSite SomeOtherSite { get; set; }
}
public class MySite
{
[XmlElement(ElementName="Name")]
public string Name { get; set; }
[XmlElement(ElementName="URL")]
public string URL { get; set; }
[XmlElement(ElementName="SecondName")]
public string SecondName { get; set; }
[XmlAttribute(AttributeName="Resource")]
public string Resource { get; set; }
}
Plus, I didn't need any custom media formatter. And from one of the posts by https://stackoverflow.com/users/1855967/elisabeth , I learned that we should not touch the generated file from xsd.exe tool. So I explicitly set to use the XmlSerializer instead of the DataContractSerializer used by default:
var formatters = new List<MediaTypeFormatter>()
{
new XmlMediaTypeFormatter(){ UseXmlSerializer = true }
};
Im new to Json and so i need your help to deserialize something.
I have a httpclient sending a webrequest:
HttpClient http = new HttpClient();
HttpResponseMessage response = await http.GetAsync(JsonBaseuri + IDInput.Text.ToString());
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
InventoryJsonData.RootObject root1 = new InventoryJsonData.RootObject();
root1 = JsonConvert.DeserializeObject<InventoryJsonData.RootObject>(content);
The RootClass is defined as:
class InventoryJsonData
{
public class RootObject
{
public bool Success { get; set; }
public object Error { get; set; }
public double Price { get; set; }
public string Username { get; set; }
}
}
I get an error and i dont know if my code is right for what i want to do. I want to get a root1 object with the Attributes from the Json data from the webrequest. What did i do wrong?
Similar exception occur when use VS2015 and Newtonsoft.Json 7.0 version. If you use version 7 of serializer maybe just try downgrade it to v6. Use nuget to change version