https://support.cex.io/requests/3862Kurze Zwischenfrage: zu Hause programmiere ich ja mit der DreamSpark-Version von Visual Studio 2013 Ultimate - in der Schule programmieren wir mit Visual Studio 2012 Express - Kann es sein, dass die Funktion zum Schreiben der Daten aus der API in einen String bei mir (VS Ultimate 2013) nicht mehr geht, weil das gleiche Projekt mit den gleichen Daten in der Schule (VS Express 2012) geöffnet war?
Was ich noch vor habe, damit dieses Thema gelöst werden kann:
- Der JSON-Deserializer gibt ja durch den Timer jede Sekunde Werte aus, die eben hoffentlich double-Werte mit dem Namen und dem Inhalt der jeweiligen Daten sind. Diese Daten müssen im Programm (UI) ja irgendwie angezeigt werden, bzw. irgendwie vorbereitet werden, damit mit eben diesen Double-Werten Berechnungen gemacht werden können. In meinem Fall ist es die Aufgabe simpel gesagt: “Schreibe jede Sekunde den Wert low aus API-Abfrage als string in label1.Text”
Meine Vermutung dabei war es, dass diese Ausgabe vom JSON Deserializer warum auch immer keine Double-Werte sind und irgendwie konvertiert werden müssen bevor sie das Programm als Double erkennt.
Über die Schule haben wir als Buch “Einstieg in Visual C# 2012” von Galileo Computing (ISBN: 978-3-8362-1960-0) - das führt zu Anfang ziemlich langwierig in Berechnungen und die verschiedenen Arten irgendwas abzuspeichern ein… In den ersten 2 Kapiteln habe ich da noch nichts von der Möglichkeit Daten als “Property” zu speichern gelesen - aber ich werd mal nachschauen was da so zu finden ist
Ich tippe meine Gedanken während des Lernens immer direkt hier ein - ich gebe ja zu, es werden längere Beiträge, aber so hilft es mir wenigstens
TickData ist doch eine Klasse mit mehreren Funktionen (für je ein Wert der API) - und, es ist doch durch public class TickData bereits eine Klasse namens TickData konfiguriert… Also wären die Klassen für den JSON Deserializer schon gegeben.
Zu Properties gibt das Buch folgendes Beispiel (das ich hier mal zitiere:
Form1.cs
[CSHARP]
using System;
using System.Windows.Forms;
namespace Eigenschaftsmethode
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void cmdAnzeigen_Click(object sender, EventArgs e)
{
Fahrzeug vespa = new Fahrzeug();
lblAnzeige.Text = "Geschwindigkeit: " +
vespa.Geschwindigkeit;
vespa.beschleunigen(120);
// vespa.Geschwindigkeit = 50;
lblAnzeige.Text += "
Geschwindigkeit: " +
vespa.Geschwindigkeit;
}
}
}
[/CSHARP]
Fahrzeug.cs
[CSHARP]
namespace Eigenschaftsmethode
{
class Fahrzeug
{
private int geschwindigkeit;
public int Geschwindigkeit
{
get
{
return geschwindigkeit;
}
private set
{
if (value > 100)
geschwindigkeit = 100;
else if (value < 0)
geschwindigkeit = 0;
else
geschwindigkeit = value;
}
}
public void beschleunigen(int wert)
{
Geschwindigkeit += wert;
}
}
}
[/CSHARP]
Beide Dateien haben den gleichen Namespace, bedeutet, die Klassen aus den beiden Dateien könnten auch in einer Datei (in meinem Fall die Form1.cs) ausgeführt werden. Genau dies ist ja mit meinem public partial class Form1 : Form - und public class TickData gegeben.
…
Das Beispiel ruft die Daten mit
[CSHARP] Fahrzeug vespa = new Fahrzeug();
lblAnzeige.Text = "Geschwindigkeit: " +
vespa.Geschwindigkeit;[/CSHARP]
ab - frei übersetzt nehme ich jetzt einfach mal TickData APIdatenDeserialized = new TickData(); für mein Programm…
Da ich die Werte ja im Label ausgeben will, müssen aus den Daten Strings werden.
Also APIlow.Text = Convert.ToString(APIdaten.low); usw.
Endlich spuckt VS 2013 keinen Fehler mehr aus…
Damit nehme ich mal an, dass ich die Daten aus dem Deserializer erfolgreich umgesetzt sind.
und dank einer Neuerung in VS 2013 sehe ich direkt die Anzahl der Verweise über den jeweiligen Befehlen in der TickData-Klasse - diese zeigen nun endlich einen Verweis an.
Einziges über bleibendes Problem:
refresh_Tick führt (bei einer Zeitspanne von 1050 ms), den Befehl zum Abrufen der API nicht mehr regelmäßig aus.
Problemanalyse:
private void Form1_Load ruft zu erst alle Daten aus der API ab (weil der Timer es ja erst eine Sekunde später machen würde), danach aktiviert sie den Timer und löscht die Werte in den Labels, die ich im Designer immer mit Fülltexten (zur Übersicht) beschreibe.
[CSHARP]
private void Form1_Load(object sender, EventArgs e)
{
APIdata = new System.Net.WebClient().DownloadString(“https://cex.io/api/ticker/GHS/BTC”);
refresh.Enabled = true;
// Löschen der Beispielwerte für die Übersicht beim Programmstart
APIask.Text = "";
APIbid.Text = "";
APIlast.Text = "";
APIhigh.Text = "";
APIlow.Text = "";
APIvolume.Text = "";
//Erstes Laden der Werte bei Programmstart (timer erst eine Sekunde später)
}[/CSHARP]
aus irgendeinerm Grund wird der erste und der zweite Befehl in Form1_Load ignoriert, obwohl das Programm beim Ausführen ja eben ausgeführt wird und damit diese void ja ausführen müsste… - Strg+Klick auf den Link öffnet die URL ja in einem Browserfenster innerhalb von Visual Studio - dieser bleibt auf “Wird geladen…” stehen und kommt irgendwann zu einem Timeout, obwohl die Daten in meinem Chrome-Browser problemlos abrufbar bleiben…
- Schritt:
Ich nutze den Button zum Anzeigen der reinen API-Daten - Dieser zeigt, auch wenn das Programm einige Sekunden lang lief immer noch nichts an, schreibe ich die Funktion zum Abrufen der API noch einmal vor den Befehl der Messagebox, werden die API-Daten direkt angezeigt. - Das Abrufen der Daten klappt also.
Auch die Labels die bei Form1_Load eigentlich geleert werden müssten werden nicht geleert - Ich nehme mal stark an, dass Form1_Load einfach nicht ausgeführt wird - Im Designer heißt mein Fenster aber weiterhin Form1… - Würde es anders heißen, würde die Fehlerliste ja auch Fehler anzeigen.
Irgendwie erkenne ich da des Rätsels Lösung noch nicht, weil eigentlich alles richtig gesetzt ist - das wäre auch das allerletzte, was ich noch machen müsste um das Problem in diesem Thread zu lösen und ihn als “gelöst” zu markieren…
Einzigste logische Erklärung: der Anbieter der API (also CEX.io) sperrt gewisse User Agents von Webbrowsern im vornherein aus.
Dazu habe ich mal ein Supportticket bei deren System gemacht: https://support.cex.io/requests/3862
Meine Aktuelle Projektdatei:
[CSHARP]
/* Programmierer: ****************
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Diagnostics;
using System.IO;
using Newtonsoft.Json;
namespace CEX.io_Windows2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string APIdata = “”;
private void refresh_Tick(object sender, EventArgs e)
{
APIdata = new System.Net.WebClient().DownloadString(“https://cex.io/api/ticker/GHS/BTC”); //API download
var jsonString = APIdata; //Newtonsoft.Json-config
TickData tick = JsonConvert.DeserializeObject<TickData>(jsonString); //JSON deserialisation starten
TickData APIdatenDeserialized = new TickData();
APIlow.Text = Convert.ToString(APIdatenDeserialized.low);
APIhigh.Text = Convert.ToString(APIdatenDeserialized.high);
APIlast.Text = Convert.ToString(APIdatenDeserialized.last);
APIask.Text = Convert.ToString(APIdatenDeserialized.ask);
APIbid.Text = Convert.ToString(APIdatenDeserialized.bid);
APIvolume.Text = Convert.ToString(APIdatenDeserialized.volume);
/* APIlow.Text = TickData.low;
APIhigh.Text = Convert.ToString(high);
APIlast.Text = Convert.ToString(last);
APIbid.Text = Convert.ToString(bid);
APIask.Text = Convert.ToString(ask); */
//Properties-HowTo: http://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx
}
private void button1_Click(object sender, EventArgs e) //Anzeige der reinen API-Daten
{
//APIdata = new System.Net.WebClient().DownloadString("https://cex.io/api/ticker/GHS/BTC");
MessageBox.Show(APIdata, "Here's RAW data *hrhrhr*", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void Form1_Load(object sender, EventArgs e)
{
APIdata = new System.Net.WebClient().DownloadString("https://cex.io/api/ticker/GHS/BTC");
refresh.Enabled = true;
// Löschen der Beispielwerte für die Übersicht beim Programmstart
APIask.Text = "";
APIbid.Text = "";
APIlast.Text = "";
APIhigh.Text = "";
APIlow.Text = "";
APIvolume.Text = "";
//Erstes Laden der Werte bei Programmstart (timer erst eine Sekunde später)
}
public class TickData //Newtonsoft.json-config
{
public Int64 timestamp { get; set; }
public double low { get; set; }
public double high { get; set; }
public double volume { get; set; }
public double last { get; set; }
public double bid { get; set; }
public double ask { get; set; }
}
//Copyright-message
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("http://erbloggt.de");
}
}
class DeserializeToString
{
/* private double timestamp, low, high, volume, last, bid, ask;
public double low
{
get { return low; }
set { low }
}
//usw… */
}
}
/*
- ab hier gibts verwaiste alte Ideen, die ich mal in dem Programm hatte, die sich aber irgendwie nicht
- bewährt haben, irgendwie aber zu schade zum Verwerfen sind…
*/
/* public static string ConvertStringArrayToString(string[] array)
{
StringBuilder builder = new StringBuilder();
foreach (string value in splittedData)
{
builder.Append(value);
}
return builder.ToString();
}*/
// string html = new System.Net.WebClient().DownloadString(“http://twitter.com”);
/*WebRequest wrGETURL = WebRequest.Create(“https://cex.io/api/ticker/GHS/BTC”);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
using (StreamReader objReader = new StreamReader(objStream))
{
string sLine = String.Empty;
while ((sLine = objReader.ReadLine()) != null)
{
Debug.WriteLine(sLine);
APIdata = sLine;
}
} */
[/CSHARP]
*** Edit ***
So - vorheriges Problem gelöst, nächstes Problem da…
[CSHARP]
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
[/CSHARP]
ein Freund machte mich darauf aufmerksam, dass irgendwie mein Form1_Load zerstört sei und obiger Code löst das vorherige Problem.
Nächstes Problem
Die Ausgabe zeigt immer “0” an, anstelle der Strings, die durch den Deserializer ja rauskommen sollten.
Screenshot:

Projekt:
[CSHARP]
/* Programmierer: *************
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Diagnostics;
using System.IO;
using Newtonsoft.Json;
namespace CEX.io_Windows2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
string APIdata = “”;
private void refresh_Tick(object sender, EventArgs e)
{
APIdata = new System.Net.WebClient().DownloadString(“https://cex.io/api/ticker/GHS/BTC”); //API download
var jsonString = APIdata; //Newtonsoft.Json-config
TickData tick = JsonConvert.DeserializeObject<TickData>(jsonString); //JSON deserialisation starten
TickData APIdatenDeserialized = new TickData();
APIlow.Text = Convert.ToString(APIdatenDeserialized.low);
APIhigh.Text = Convert.ToString(APIdatenDeserialized.high);
APIlast.Text = Convert.ToString(APIdatenDeserialized.last);
APIask.Text = Convert.ToString(APIdatenDeserialized.ask);
APIbid.Text = Convert.ToString(APIdatenDeserialized.bid);
APIvolume.Text = Convert.ToString(APIdatenDeserialized.volume);
/* APIlow.Text = TickData.low;
APIhigh.Text = Convert.ToString(high);
APIlast.Text = Convert.ToString(last);
APIbid.Text = Convert.ToString(bid);
APIask.Text = Convert.ToString(ask); */
//Properties-HowTo: http://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx
}
private void button1_Click(object sender, EventArgs e) //Anzeige der reinen API-Daten
{
//APIdata = new System.Net.WebClient().DownloadString("https://cex.io/api/ticker/GHS/BTC");
MessageBox.Show(APIdata, "Here's RAW data *hrhrhr*", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void Form1_Load(object sender, EventArgs e)
{
APIdata = new System.Net.WebClient().DownloadString("https://cex.io/api/ticker/GHS/BTC");
refresh.Enabled = true;
// Löschen der Beispielwerte für die Übersicht beim Programmstart
APIask.Text = "";
APIbid.Text = "";
APIlast.Text = "";
APIhigh.Text = "";
APIlow.Text = "";
APIvolume.Text = "";
//Erstes Laden der Werte bei Programmstart (timer erst eine Sekunde später)
}
public class TickData //Newtonsoft.json-config
{
public Int64 timestamp { get; set; }
public double low { get; set; }
public double high { get; set; }
public double volume { get; set; }
public double last { get; set; }
public double bid { get; set; }
public double ask { get; set; }
}
//Copyright-message
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("http://erbloggt.de");
}
}
class DeserializeToString
{
/* private double timestamp, low, high, volume, last, bid, ask;
public double low
{
get { return low; }
set { low }
}
//usw… */
}
}
/*
- ab hier gibts verwaiste alte Ideen, die ich mal in dem Programm hatte, die sich aber irgendwie nicht
- bewährt haben, die aber trotzdem aus welchem Grund auch immer zu Schade dafür sind gelöscht zu werden.
*/
/* public static string ConvertStringArrayToString(string[] array)
{
StringBuilder builder = new StringBuilder();
foreach (string value in splittedData)
{
builder.Append(value);
}
return builder.ToString();
}*/
// string html = new System.Net.WebClient().DownloadString(“http://twitter.com”);
/*WebRequest wrGETURL = WebRequest.Create(“https://cex.io/api/ticker/GHS/BTC”);
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
using (StreamReader objReader = new StreamReader(objStream))
{
string sLine = String.Empty;
while ((sLine = objReader.ReadLine()) != null)
{
Debug.WriteLine(sLine);
APIdata = sLine;
}
} */
[/CSHARP]