Laden...

Httpclient Anfrage- Daten aus Antwort weiter verabeiten

Erstellt von chh2807 vor 2 Jahren Letzter Beitrag vor 2 Jahren 583 Views
Thema geschlossen
C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren
Httpclient Anfrage- Daten aus Antwort weiter verabeiten

Hallo,

mit dem folgenden Code versuche ich mich mit einer Gegenstelle zu verbinden, eine Antwort zu bekommen und im Programm erstmal aus zu geben. Weiter verarbeiten wäre dann der nächste Schritt.

Aber wie kann ich die Daten, die aus dem Task kommen, so aufbereiten das sie beispielsweise in eine Textbox / Richtextbox angezeigt werden? Als näcshtes würde ich die Antwort auf bestimmte Zeichenketten durchsuchen und diese dann ausgeben wollen, was ja im entsprechenden Format kein Thema wäre. Aber erstmal dahin kommen:D.

Vielen dank!


 async Task<string> GetResponseString()
        {
            var userName = "test";
            var passwd = "test";
            var url = "127.0.0.10";

            using var client = new HttpClient();

            var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));

            var result = await client.GetAsync(url);

            var content = await result.Content.ReadAsStringAsync();
            //Console.WriteLine(content);

            return content;
        }

        private void RichTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {

        }

        private void connect_Click(object sender, RoutedEventArgs e)
        {
            
            GetResponseString();
            
        }

MFG
Chh

P
441 Beiträge seit 2014
vor 2 Jahren

Du musst den Task awaiten.

So kommst du an das Ergebnis.

Wann willst du die Informationen via http abrufen? Dort kannst du await nutzen.
Ein Event handler darf async void sein.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Bin mal auf die schnelle mitm Handy online, also nicht so ausführlich 😅

Oben sind ja schon 2x await drin. Ist das vom Prinzip in etwa so gemeint?


string text = await GetResponseString();

Normalerweise hab ich sonst immer Hardware-Treiber genutzt und eingebaut wenn ich mal alle halbe Jahre kleine Tools programmiert habe. Die Abfrage von Webinterfaces ist mir noch komplett neu. Sorry wenn ich mich da vielleicht etwas blöd anstelle🙈

MFG
Chh

16.807 Beiträge seit 2008
vor 2 Jahren

Hat mit der Entwicklung / Abfrage von Web Interfaces nichts zutun, sondern mit der asynchronen Programmierung.
Asynchrone Programmierung in C#

Das Thema ist aber leider so, dass - wenn Du es nicht verstehst - sehr schnell Fehler machen kannst, die die ganze Anwendung instabil machen; und leider auch nicht so einfach zu debuggen ist.
Daher unbedingt das Thema sauber durchlesen. Mit Try and Error kommst Du bei async/await leider auf keinen grünen Zweig, was die Erfahrung zeigt. Man muss das Konzept verstehen.

Aber prinzipiell: ja, Du musst sowas immer awaiten.

PS: Deine Handhabung vom HttpClient ist auch alles andere als zu empfehlen, siehe
HttpClient Klasse (System.Net.Http)
HTTP Client Hinweise in meinem Post

PPS: wenn Du eine REST API ansprechen willst, wenn Du das mit Webseite meinst, dann gibts dafür fertige Frameworks, die einem viel abnehmen.
GitHub - reactiveui/refit: The automatic type-safe REST library for .NET Core, Xamarin and .NET. Heavily inspired by Square's Retrofit library, Refit turns your REST API into a live interface.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Warum ist die Anwendung von Httpclient wie oben im Beispiel nicht zu empfehlen? Das ist ein Beispiel wie ich es im Internet sehr oft gefunden habe. Das mit der asynchronen Programmierung müßte ich mir dann mal genau anschauen und wie man damit arbeitet.

Aber hier noch mal dazu was ich eigetnlich möchte. Ich hab hier ein paar curl Befehle zum verbinden mit einem Gerät über TCP/IP, dann werden 2-3 config Files übertragen und ein Reset Befehl geschickt. Im Anschluss sollen dann Werte in Form von Listings in .xml files abgeholt und analysiert werden.

Das sieht ungefähr so aus:


curl -u admin:123456 "http://127.0.0.10/ChgPasswordWB" --data-raw "&Method=GetActiveUser" --output - 


curl -u admin:123456 "http://127.0.0.10/MeUpDnLdGenWS?Methode=FileUpLoadDD&Path=.&FileName=App.app&Dev=0&Dir=3" --data-binary @App.app


curl -u admin:123456 "http://127.0.0.10/ResetWB?bSetReset=true"

Aber anstatt einzelne Curl Befehle zu schicken, solls ein automatisierter Test, ausschließlich für interne Zwecke, werden. Da ich bisher mit CIP gearbeitet habe, also dank Treiber / Lib / fertigem CIP-Stack, alles vorbereiet hatte, wars ein einfaches einzelne Ausgangsbytes zu setzen oder Inputbytes aus zu lesen.

Wenn ich die Verbindung zum Gerät habe, bin ich weit genug.

Da ich ja selber noch dabei bin zu evaluieren wie ich das umsetze, die Frage: welchen Weg würdet ihr gehen?

MFG
Chh

16.807 Beiträge seit 2008
vor 2 Jahren

Warum ist die Anwendung von Httpclient wie oben im Beispiel nicht zu empfehlen?

Ich hab Dir zwei Links gegeben, in denen genau beschrieben ist, wieso Deine Umsetzung nicht gut ist - und wie es richtig geht. Wieso liest Du sie nicht einfach durch?
Hab ich Dir ja nicht umsonst geben 😉

TLDR; es ist logisch nicht falsch, sondern technisch ungünstig, weil der HttpClient nicht dauernd neu erzeugt werden soll.

Das ist ein Beispiel wie ich es im Internet sehr oft gefunden habe.

Ist trotzdem keine gute Umsetzung - und ja, beim HttpClient leider weit verbreitet, weshalb auch die Doku vor ~3 Jahren überarbeitet wurde, um deutlicher zu kennzeichnen, wie es richtig geht.
Steht jetzt dick und fett im ersten Beispiel, wenn Du die Doku geöffnet hättest 🙂

welchen Weg würdet ihr gehen?

Entweder mit dem HttpClient oder mit GitHub - reactiveui/refit: The automatic type-safe REST library for .NET Core, Xamarin and .NET. Heavily inspired by Square's Retrofit library, Refit turns your REST API into a live interface..
Letzteres, weil es mir fast alles in Sachen HTTP abnimmt und ich einen typisierten Umgang habe.
Für Dein Fall mag das vielleicht etwas over size sein, wenn man das typisierte nicht unbedingt will.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Du meinst diesen Teil in der Erklärung?

HttpClient soll einmal instanziiert und während der gesamten Lebensdauer einer Anwendung wieder verwendet werden. Durch das Instanziieren einer HttpClient-Klasse für jede Anforderung wird die Anzahl der verfügbaren Sockets bei starker Auslastung erschöpft. Dies führt zu SocketException-Fehlern. Im folgenden finden Sie ein Beispiel für die korrekte Verwendung von HttpClient.

Wenn ich das richtig verstehe, würde ich in meinem ersten Beispiel oben für jeden Aufruf nach Buttonclick neu Instanziieren. So sollte es ja dann besser sein oder?


public partial class MainWindow : Window
    {

        static HttpClient client = new HttpClient();

        public MainWindow()
        {
            InitializeComponent();            
        }

        async Task<string> GetResponseString(string text)
        {
            var userName = "test";
            var passwd = "test";
            var url = "127.0.0.10";            

            var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));

            var result = await client.GetAsync(url);

            string content = await result.Content.ReadAsStringAsync();
            //Console.WriteLine(content);

            return content;
        }               

        private void connect_Click(object sender, RoutedEventArgs e)
        {
                        
        }
    }


Was mich gerade viel mehr verrückt macht ist das ich, warum auch immer nichts mhr über die Richtextbox ausgeben kann. So wie ich es seit Jahren kenne und es auch überall beschrieben ist, war das.


Richtextbox.Text = "BeispieltexT" + mögliche Variable; 

Warum geht das nicht mehr? .Text oder .AppendText stehen nicht mal zur Auswahl, auch sonst nichts wie man vernünftig einen simplen Text ausgeben kann.

MFG
Chh

16.807 Beiträge seit 2008
vor 2 Jahren

Auch hier lohnt sich immer ein Blick in die Dokumentation.

Warum geht das nicht mehr? .Text oder .AppendText stehen nicht mal zur Auswahl, auch sonst nichts wie man vernünftig einen simplen Text ausgeben kann.

Dann hast Du bisher mit Windows Forms gearbeitet und verwendest nun WPF.

WinForms RichTextBox arbeitet direkt mit dem Text (über die Text Eigenschaft).
WPF funktioniert technisch anders, weshalb Du hier eine Document Eigenschaft hast; unterstützt viel komplexere Szenarien.

In WPF arbeitet man zudem nicht im Code Behind, sondern über Datenbindung.
[Artikel] MVVM und DataBinding
Das heisst, das ganze Zeug, was Du da derzeit in das Window klatscht, kommt in WPF da gar nicht rein, sondern in ein ViewModel, das dann gebunden werden kann.

Ich würde mal behaupten, dass Dir einfach die Übersichtlichkeit in .NET fehlt und Du die Dinge noch nicht so ganz unterscheiden kannst 🙂
Ist halt schwer sich zurecht zu finden, wenn man einfach (planlos?) drauf loslegt... nimm es einfach Wink mit dem Zaunpfahl hin 😉
Aber ja: die Lernhürde für WPF ist deutlich höher als für WinForms.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Danke, bin da wirklich etwas verrutscht 😭

Wäre dieser Teil denn so schon mal korrekt? Sprich die Instanzierung des Httpclients und dann die Anmeldsyntax?


static HttpClient client = new HttpClient();   

async Task<string> GetResponseString(string text)
        {
            var userName = "test";
            var passwd = "test";
            var url = "127.0.0.10";

            var authToken = Encoding.ASCII.GetBytes($"{userName}:{passwd}");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));

            var result = await client.GetAsync(url);

            string content = await result.Content.ReadAsStringAsync();
            //Console.WriteLine(content);

            return content;
        }

MFG
Chh

16.807 Beiträge seit 2008
vor 2 Jahren

Ja, nun stimmt die HttpClient Implementierung der Empfehlung.
Aber wie gesagt; das war ohnehin nur in Hinweis und macht logisch keinen Unterschied.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Mit dem Code oben hab ich leider keine Verbindung bekommen. Mit Wireshark konnte ich nicht mal etwas feststellen was rausgeschickt wurde. Möge man mich nun ruhig steinigen aber nach dem der Code oben nicht geklappt hat, hab ichs dann doch noch mal mit "WebRequest" versucht und das funktionierte auf Anhieb.

Genau das was ich brauchte um Daten vom Gerät zu lesen:


HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://127.10.0.10");
            string authInfo = "user:password";
            authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
            request.Headers.Add("Authorization", "Basic " + authInfo);
            request.Credentials = new NetworkCredential("user", "password");
            request.Method = WebRequestMethods.Http.Get;
            request.AllowAutoRedirect = true;
            request.Proxy = null;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader streamreader = new StreamReader(stream);
            string s = streamreader.ReadToEnd();
            richTextBox1.Text = "";
            richTextBox1.AppendText(s);

Jetzt mal schauen wie es in die andere Richtung geht, configfiles aufspielen.

MFG
Chh

16.807 Beiträge seit 2008
vor 2 Jahren

..und den WebRequest soll man seit Jaaaahren nicht mehr verwenden.

https://docs.microsoft.com/de-de/dotnet/api/system.net.httpwebrequest?view=net-5.0

Es wird nicht empfohlen, HttpWebRequest für die neue Entwicklung zu verwenden. Verwenden Sie stattdessen die- System.Net.Http.HttpClient Klasse.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Ich bin erstmal froh eine Sache zum Laufen gebracht zu haben. Wenn ich wüsste warum der Code weiter oben nicht funktioniert, würde ich es fixen 😅

Interessant wäre dann aber noch zu wissen was am Webrequest so falsch ist, schließlich schleppt MS das immer noch mit rum, auch in VS2019.

MFG
Chh

16.807 Beiträge seit 2008
vor 2 Jahren

VS2019 ist eine Entwicklungsumgebung und keine Runtime.
=> [FAQ] Das .NET Ökosystem - .NET, .NET Core, .NET Standard, NuGet und Co
In der Runtime ist es nur noch aus Kompatibilitätsgründen, wie so oft bei Enterprise-Grade Entwicklungsplattformen.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Na und warum soll man httpwebrequest nicht mehr nutzen? Weil Microsoft neue Funktionen verkaufen möchte oder gibt es valide Gründe, die mich daran hindern sollten bei einem nicht zeitkritischen, internen Testaufbau der niemals einen Kunden sehen wird, zu nutzen?

Außerdem bringt mir der tollste neue, aktuelle Code rein gar nichts wenn er nicht funktioniert. Ich hab gefragt ob der Code so korrekt ist. Antwort war "ja". Wäre ich Profi und hätte die Weißheit mit Löffeln gefuttert, würde ich nicht hier fragen. Prüfe ich dann den Netzwerkport mit Wireshark kommt da rein gar nichts, nicht mal ne abgelehnte Verbindung. Funktioniert ja super das Ganze 😁

Selbst damit war ich erfolgreicher, damit hab ich wenigstens eine "401 not authorized" Meldung zurück bekommen:


//WebClient myWebclient = new WebClient();
            WebClient wc = new WebClient();

            NetworkCredential nc = new NetworkCredential("user", "passwort");
            wc.Credentials = nc;

            byte[] response = wc.DownloadData("http://127.0.0.10");
            richTextBox1.AppendText(Encoding.ASCII.GetString(response)); 

Da wird vermutlich das AuthToken fehlen, was ich bei der Methode unten nutze. Hat jemand ne Idee wie ich das noch hineinbekomme?

Dieser Code funktioniert hingegen tadellos, zumindest für Abfragen:


HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://127.0.0.10");
            string authInfo = "user:passwort";
            authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
            request.Headers.Add("Authorization", "Basic " + authInfo);
            request.Credentials = new NetworkCredential("user", "Passwort");
            request.Method = WebRequestMethods.Http.Get;
            request.AllowAutoRedirect = true;
            request.Proxy = null;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader streamreader = new StreamReader(stream);
            string s = streamreader.ReadToEnd();
            richTextBox1.Text = "";
            richTextBox1.AppendText(s);

MFG
Chh

P
441 Beiträge seit 2014
vor 2 Jahren

Microsoft verkauft dir erst einmal gar nichts, sondern sie bieten dir mit der Klasse HttpClient eine weiterentwickelte Klasse, die neuere und performantere Paradigmen nutzt.

Das unterliegende Prinzip (=http) ist jedoch dasselbe, alleine die API ist anders für dich.
Du hast eine ganze Menge Werkzeuge an der Hand, um festzustellen was nicht funktioniert.

Du kannst einzelne Schritte mit dem Debugger testen, damit siehst du auch, ob der Code ausgeführt wird.
Du kannst Wireshark oder einen Debugger Proxy wie Fiddler nutzen um dir Unterschiede zwischen den http requests anschauen.

Da hilft herumschreien, dass der WebClient aber funktioniert halt gar nicht.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Das hat mit rumschreien nichts zu tun wenn man sich veräppelt vorkommt. Ich habe explizit um Hilfe gefragt, eine vorgeschlagene Lösung die nicht funktioniert wird als "gut" oder zumindest als "ausreichend" bezeichnet und die funktionierende Lösung ist schlecht. Ok. Aber auf mehrmalige Nachfrage, warum und wieso etwas nicht ok ist, bekomme ich natürlich keine Antwort.

Wenn ich alles wüßte würde ich nicht fragen. Ich hab einleitend mehrmals daruf hingewiesen das ich mit den Webtechniken von C# komplett fremd bin.
Und du hast meine Rückfrage oben auch nicht beantwortet.

Gibts vielleicht auch noch jemanden der einem wirklich helfen will oder gehts nur ums Diskutieren um des Diskutierens Willen?

MFG
Chh

16.807 Beiträge seit 2008
vor 2 Jahren

Na und warum soll man httpwebrequest nicht mehr nutzen?

Warum sollen wir Dir denn dauernd die Dokumentation vorkauen, wenn Du die Antwort einfach selbst lesen kannst?
HttpWebRequest / WebClient sind völlig veraltete Implementierungen. Angefangen bei blockierendem Code bis hin zur Security Implementierung zB von TLS.
Entsprechend wirst Du in Zukunft Probleme bekommen, wenn die implementierten Wege abgekündigt werden.
HttpClient hingegen ist modern, sowohl die Implementierung wie auch die Security.

Glaubst in der Doku steht das als dicke Warnung einfach um möglichst vielen Entwicklern das Leben schwer zu machen?
Aber hey: Du machst was Du willst und ignorierst die Tipps bzw. kanzelst sie ab. Warum soll ich mir dann die Mühe machen Dir mehr zu helfen, wenn Du eh machst, wie Du es am besten findest...?
Das ist Zeitverschwendung für mich.

Weil Microsoft neue Funktionen verkaufen möchte oder gibt es valide Gründe,

Du hast da mächtig nicht verstanden, wie eine Entwicklungsumgebung, egal ob Java, .NET oder NodeJS funktioniert - und warum halt ab und Zeug angekündigt werden muss.
Und dass es nicht funktioniert, liegt nicht an der Technik, sondern weil Du einfach - mein Gesamteindruck - einfach los programmiert hast ohne, dass Du Dich beschäftigt hast, wie es funktioniert. Wir haben Dich auf Dokus verwiesen, in denen Dinge beantwortet werden, und im nächsten Post fragst nach, was im ersten Absatz des zuvor gegebenen Links steht.
Aus Bequemlichkeit suchst jetzt halt bei Microsoft die Schuld. Das muss einer verstehen...

Wenn ich alles wüßte würde ich nicht fragen.

Ja, ist manchmal nicht einfach, Software zu entwickeln. Ja, niemand wurde mit der Intelligenz geboren.
Aber genau deswegen gibt es Dokumentationen, die ein Entwickler lesen muss. Das gehört zum Job.

Keine hier hat gesagt "gut" zu Deiner logischen Implementierung, sondern zur technischen bei der Nachfrage von Dir zu async/await.
Wenn Du nicht mal das einordnen kannst, wie soll man Dir dann helfen....? Und dann kommt jetzt ein Satz, in dem Du Leute diskreditierst, dass jemand nicht wirklich helfen will - nur weil Du die Tipps im Beitrag, die Du bislang nicht umgesetzt hast, ignorierst, missachtest oder was auch immer.

Keiner hier verbringt seine Freizeit, um Dich zu ärgern oder Dich auf die falsche Fährte zu bringen.
Und wenn Du das den Leuten vorwirst, dann wirst halt in Zukunft von den Leuten auch keine Hilfe mehr bekommen.

Nimm die Hilfe an, oder lass es bleiben. Aber schieb die Schuld nicht auf andere.

C
chh2807 Themenstarter:in
33 Beiträge seit 2015
vor 2 Jahren

Keine hier hat gesagt "gut" zu Deiner logischen Implementierung

Ja was denn nun?

Ja, nun stimmt die HttpClient Implementierung der Empfehlung.

Aber logisch, ich verstehe hier etwas nicht.....

Und dann kommt jetzt ein Satz, in dem Du Leute diskreditierst, dass jemand nicht wirklich helfen will - nur weil Du die Tipps im Beitrag, die Du bislang nicht umgesetzt hast, ignorierst, missachtest oder was auch immer.

Ja klar, die Rückfrage wie ich die Antwort "awaite" wurde bis heute nicht beantowrtet, da liegen mittlierweile ein paar Tage dazwischen! Aber klar, ich bin Schuld... Unfassbar...
Und die korrekte Instanziierung hab ich auch umgesetzt nach Rückfragen. Aber ich setze Tipps nicht um.....

Komplette Verarschung, echt....

MFG
Chh

Hinweis von Abt vor 2 Jahren

Denke mit diesen weisen Worten ist das Thema auch beendet 😃
Thema ist geschlossen.

Thema geschlossen