I am trying to invoke a method from the Main() method of a .net core console application that should display two properties from an external api but the console is only displaying Hello World and no other result data, I also want the console to stay put and not disappear off the screen. All help pointers are most welcome and thank you in advance!
UserItem.cs -
public class UserItem
{
public UserItem(string name, string url)
{
Name = name;
Url = url;
}
public string Name { get; set; }
public string Url { get; set; }
}
Program.cs -
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
GetUser();
}
// retrieve all.
public static async void GetUser()
{
//baseUrl
string baseUrl = "http://pokeapi.co/api/v2/pokemon/";
try
{
// HttpClient implements a IDisposable interface.
using (HttpClient client = new HttpClient())
{
//initiate Get Request (await will execute the using statement in order).
using (HttpResponseMessage res = await client.GetAsync(baseUrl))
{
//get content from response, then convert it to a c# object.
using (HttpContent content = res.Content)
{
//assign content to data variable by converting into a string using await.
var data = await content.ReadAsStringAsync();
//If the data is not null log convert the data using newtonsoft JObject Parse class method.
if (content != null)
{
//log data object in the console
Console.WriteLine("data------------{0}", JObject.Parse(data)["results"]);
}
else
{
Console.WriteLine("NO Data----------");
}
}
}
}
}
catch (Exception exception)
{
Console.WriteLine("Exception Hit------------");
Console.WriteLine(exception);
}
}
}
using System;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
//Waits the API response
GetUser().Wait();
//Waits until a key is pressed.
Console.ReadKey();
}
// retrieve all.
public static async Task GetUser()
{
//...
}
}
}
Related
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; }
}
I am trying to consume a web service. It's an XML based service. I mean response in XML format. The code is working fine. However, I do not want to use task.Wait(). Please let me know how I can replace it with async/await.
Below is my code :
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
Program obj = new Program();
var result = obj.GetData().Result;
}
public async Task<string> GetData()
{
string url =
"https://test.net/info.php?akey=abcd&skey=xyz";
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync(url).Result;
var responseValue = string.Empty;
if (response != null)
{
Task task = response.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (var reader = new StreamReader(stream))
{
responseValue = reader.ReadToEnd();
}
});
task.Wait(); // How I can replace it and use await
}
return responseValue;
}
}
[XmlRoot(ElementName = "Info")]
public class Test
{
[XmlAttribute(AttributeName = "att")]
public string SomeAttribute{ get; set; }
[XmlText]
public string SomeText{ get; set; }
}
}
You already are in an async context, so just use await:
var stream = await response.Content.ReadAsStreamAsync();
using (var reader = new StreamReader(stream))
{
responseValue = reader.ReadToEnd();
}
That said, you should check all your calls:
HttpResponseMessage response = await client.GetAsync(url);
and make your main async, too and while we are at it make the method static:
public static async Task Main)
{
var result = await GetData();
}
where your method signature is:
public static async Task<string> GetData()
The static isn't required, but you will find parallel and/or asynchronous programming is a lot easier if you have as little side effects as possible.
You can make Main method async as well and await GetData
static async Task Main(string[] args)
{
Program obj = new Program();
var result = await obj.GetData();
}
I take data from Bittrex without WebSocket by this way
request = WebRequest.Create("https://bittrex.com/api/v1.1/public/getticker?market=USDT-BTC");
request.Credentials = CredentialCache.DefaultCredentials;
response = (HttpWebResponse)request.GetResponse();
dataStream = response.GetResponseStream();
reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
reader.Close();
dataStream.Close();
response.Close();
date = JsonConvert.DeserializeObject(responseFromServer);
It is very easy way and it is working on Bittrex. But I did a lot off request. I need do it on Bitfinex but I have the exeption "Too many request". As I understood I need WebSocket for this. By this adress https://api.bitfinex.com/v1/pubticker/BTCUSD. Somebody can show easy code to understand how I need to conect and write in Console info from WebSocket. Thanks!
BIttrex release in March beta version of new site and WebSocket. GitHub repository have samples for usage WebSocket channel to subscribe for events.
Here is C# example:
using System;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using Microsoft.AspNet.SignalR.Client;
namespace WebsocketSample
{
public sealed class BittrexWebsocket
{
public delegate void BittrexCallback(string info);
private HubConnection _hubConnection { get; }
private IHubProxy _hubProxy { get; }
private BittrexCallback _updateExchangeState { get; }
private BittrexCallback _updateOrderState { get; }
private BittrexCallback _updateBalanceState { get; }
public BittrexWebsocket(
string connectionUrl,
BittrexCallback updateExchangeState,
BittrexCallback updateOrderState,
BittrexCallback updateBalanceState
)
{
// Set delegates
_updateExchangeState = updateExchangeState;
_updateOrderState = updateOrderState;
_updateBalanceState = updateBalanceState;
// Create connection to c2 SignalR hub
_hubConnection = new HubConnection(connectionUrl);
_hubProxy = _hubConnection.CreateHubProxy("c2");
// Register callback for uE (exchange state delta) events
_hubProxy.On(
"uE",
exchangeStateDelta => _updateExchangeState?.Invoke(exchangeStateDelta)
);
// Register callback for uO (order status change) events
_hubProxy.On(
"uO",
orderStateDelta => _updateOrderState?.Invoke(orderStateDelta)
);
// Register callback for uB (balance status change) events
_hubProxy.On(
"uB",
balanceStateDelta => _updateBalanceState?.Invoke(balanceStateDelta)
);
_hubConnection.Start().Wait();
}
public void Shutdown() => _hubConnection.Stop();
// marketName example: "BTC-LTC"
public async Task<bool> SubscribeToExchangeDeltas(string marketName) => await _hubProxy.Invoke<bool>("SubscribeToExchangeDeltas", marketName);
// The return of GetAuthContext is a challenge string. Call CreateSignature(apiSecret, challenge)
// for the response to the challenge, and pass it to Authenticate().
public async Task<string> GetAuthContext(string apiKey) => await _hubProxy.Invoke<string>("GetAuthContext", apiKey);
public async Task<bool> Authenticate(string apiKey, string signedChallenge) => await _hubProxy.Invoke<bool>("Authenticate", apiKey, signedChallenge);
// Decode converts Bittrex CoreHub2 socket wire protocol data into JSON.
// Data goes from base64 encoded to gzip (byte[]) to minifed JSON.
public static string Decode(string wireData)
{
// Step 1: Base64 decode the wire data into a gzip blob
byte[] gzipData = Convert.FromBase64String(wireData);
// Step 2: Decompress gzip blob into minified JSON
using (var decompressedStream = new MemoryStream())
using (var compressedStream = new MemoryStream(gzipData))
using (var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
{
deflateStream.CopyTo(decompressedStream);
decompressedStream.Position = 0;
using (var streamReader = new StreamReader(decompressedStream))
{
return streamReader.ReadToEnd();
}
}
}
public static string CreateSignature(string apiSecret, string challenge)
{
// Get hash by using apiSecret as key, and challenge as data
var hmacSha512 = new HMACSHA512(Encoding.ASCII.GetBytes(apiSecret));
var hash = hmacSha512.ComputeHash(Encoding.ASCII.GetBytes(challenge));
return BitConverter.ToString(hash).Replace("-", string.Empty);
}
}
class Program
{
static public BittrexWebsocket.BittrexCallback CreateCallback(string name)
{
//
// In a real app, your code would do something useful based on the
// information accompanying each event.
//
return (info) =>
{
Console.WriteLine($"Callback Invoked: {name}");
Console.WriteLine(
BittrexWebsocket.Decode(info)
);
};
}
static void Main(string[] args)
{
Task task = Task.Run(
async () =>
{
string apiKey = "YOUR_API_KEY";
string apiSecret = "YOUR_API_SECRET";
string baseUrl = "https://beta.bittrex.com/signalr";
var btx = new BittrexWebsocket(
baseUrl,
CreateCallback("exchange"),
CreateCallback("order"),
CreateCallback("balance")
);
// If we successfully authenticate, we'll be subscribed to the uO and uB events.
var isAuthenticated = await btx.Authenticate(
apiKey,
BittrexWebsocket.CreateSignature(apiSecret, await btx.GetAuthContext(apiKey))
);
// Register for orderbook updates on the BTC-ETH market
await btx.SubscribeToExchangeDeltas("BTC-ETH");
});
task.Wait();
Console.WriteLine("Press enter to exit sample...");
Console.ReadLine();
}
}
}
Run in PackageManager Console to add SignalR dependency:
Install-Package Microsoft.AspNet.SignalR.Client -Version 2.3.0
Also to connect you need get Key and Secret from your account on Bittrex.
string apiKey = "YOUR_API_KEY";
string apiSecret = "YOUR_API_SECRET";
For Bitfinex you can try next code:
using System;
using WebSocketSharp;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
using (var ws = new WebSocket("wss://api.bitfinex.com/ws/2"))
{
ws.OnMessage += (sender, e) => Console.WriteLine(e.Data);
ws.Connect();
ws.Send("{\"event\":\"subscribe\", \"channel\":\"ticker\", \"pair\":\"BTCUSD\"}");
Console.ReadKey(true);
}
}
}
}
Requires dependency from Nuget:
Install-Package WebSocketSharp-NonPreRelease -Version 1.0.0
I am trying to validate an API response but I can't seem to understand how to use the content of the response.
This is my response :
"{\"On\": false, \"value\": null,}"
And I would like to test for the value of "On" (if its true then... or false then...).
Here is my code so far :
using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Net.Http.Headers;
namespace APITest
{
class Program
{
static void Main(string[] args)
{
PostRequest("My API");
Console.ReadKey();
}
async static void PostRequest(string url)
{
IEnumerable<KeyValuePair<string, string>> queries = new
List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("Test","1")
};
HttpContent q = new FormUrlEncodedContent(queries);
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);
}
}
}
}
}
}
You create a class which represents that JSON structure and use a JSON serializor to de-serialize your string representation to an object of that class and use it as needed
Here i show you do it with JSON.NET
string mycontent = await content.ReadAsStringAsync();
var result= Newtonsoft.Json.JsonConvert.DeserializeObject<ApiResult>(mycontent);
if (result!= null)
{
if (result.On)
{
//do something, may be read, result.Value
}
else
{
//do something else
}
}
Assuming you have a class like this
public class ApiResult
{
public bool On { set; get; }
public string Value { set; get; }
}
Up until now, I've been making synchronous HttpWebRequest calls in WinForms applications. I want to start doing it asynchronously so as to not block the UI thread and have it hang. Therefore, I am attempting to switch to HttpClient, but I am also new to async and tasks and don't quite get it, yet.
I can launch the request and get a response and isolate the data I want (result, reasonPhrase, headers, code) but don't know how to get that back for display in textBox1. I also need to capture ex.message and return to the form if a timeout or cannot connect message occurs.
Every single example I see has the values written to Console.WriteLine() at the point they are available, but I need them returned back to the form for display and processing and have a hard time understanding how.
Here's a simple example:
namespace AsyncHttpClientTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "calling Test()...\r\n";
DownloadPageAsync();
// need to get from DownloadPageAsync here: result, reasonPhrase, headers, code
textBox1.AppendText("done Test()\r\n");
}
static async void DownloadPageAsync()
{
// ... Use HttpClient.
using (HttpClient client = new HttpClient())
{
try
{
using (HttpResponseMessage response = await client.GetAsync(new Uri("http://192.168.2.70/")))
{
using (HttpContent content = response.Content)
{
// need these to return to Form for display
string result = await content.ReadAsStringAsync();
string reasonPhrase = response.ReasonPhrase;
HttpResponseHeaders headers = response.Headers;
HttpStatusCode code = response.StatusCode;
}
}
}
catch (Exception ex)
{
// need to return ex.message for display.
}
}
}
}
}
Any helpful hints or advice?
create a model to hold the data you want to return
public class DownloadPageAsyncResult {
public string result { get; set; }
public string reasonPhrase { get; set; }
public HttpResponseHeaders headers { get; set; }
public HttpStatusCode code { get; set; }
public string errorMessage { get; set; }
}
Avoid using async void methods. Convert the method to async Task and call it in the event handler where it is allowed.
private async void button1_Click(object sender, EventArgs e) {
textBox1.Text = "calling Test()...\r\n";
var result = await DownloadPageAsync();
// Access result, reasonPhrase, headers, code here
textBox1.AppendText("done Test()\r\n");
}
static HttpClient client = new HttpClient();
static async Task<DownloadPageAsyncResult> DownloadPageAsync() {
var result = new DownloadPageAsyncResult();
try {
using (HttpResponseMessage response = await client.GetAsync(new Uri("http://192.168.2.70/"))) {
using (HttpContent content = response.Content) {
// need these to return to Form for display
string resultString = await content.ReadAsStringAsync();
string reasonPhrase = response.ReasonPhrase;
HttpResponseHeaders headers = response.Headers;
HttpStatusCode code = response.StatusCode;
result.result = resultString;
result.reasonPhrase = reasonPhrase;
result.headers = headers;
result.code = code;
}
}
} catch (Exception ex) {
// need to return ex.message for display.
result.errorMessage = ex.Message;
}
return result;
}
The HttpClientshould also not be created every time the download is called.
Refer to What is the overhead of creating a new HttpClient per call in a WebAPI client?