HttpCLient Post Request Beispiel funktioniert nicht

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 28 Antworten in diesem Thema. Der letzte Beitrag () ist von siycah.

    HttpCLient Post Request Beispiel funktioniert nicht

    Guten Morgen :)

    ich versuche gerade einen HttpCLient Post Request zu programmieren und stosse gleich am Anfang an meine Grenzen. Hier mein Codeschnipsel:

    C#-Quellcode

    1. using System.Net.Http.Headers;
    2. var client = new HttpClient();
    3. var request = new HttpRequestMessage
    4. {
    5. Method = HttpMethod.Post,
    6. RequestUri = new Uri("https://scrapesoft-music-lyrics.p.rapidapi.com/api/lyrics?access_token=%7BaccessToken%7D"),
    7. Headers =
    8. {
    9. { "X-RapidAPI-Key", "XXXXXXXXXXX" },
    10. { "X-RapidAPI-Host", "scrapesoft-music-lyrics.p.rapidapi.com" },
    11. },
    12. Content = new StringContent("{\n \"songName\": \"ENTER_SONG_NAME\",\n \"artistName\": \"ENTER_ARTIST_NAME\"\n}")
    13. {
    14. Headers =
    15. {
    16. ContentType = new MediaTypeHeaderValue("application/json")
    17. }
    18. }
    19. };
    20. using (var response = await client.SendAsync(request))
    21. {
    22. response.EnsureSuccessStatusCode();
    23. var body = await response.Content.ReadAsStringAsync();
    24. Console.WriteLine(body);
    25. }


    Funktioniert leider vorne und hinten nicht, und automatisiert nach VB übersetzen geht auch nicht.

    Bevor ich jetzt versuche den Code zu verstehen muss er natürlich erstmal funktionieren bzw. eventuell auch in VB vorliegen. Kann mir jemand vielleicht sagen, was daran falsch ist? Ich glaub der Fehler liegt gleich in Zeile 1. Da sagt er mir:

    System.Net.Http.Headers ist Namespace, wird aber wie Variable verwendet.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    C#-Quellcode

    1. using (var response = await client.SendAsync(request))
    Wenn Du response asyncron verwendest, wird die Instanz beim end using zerstört, bevor irgend etwas passiert ist.
    Nimm mal das using weg.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    kafffee schrieb:

    Was ist mit Zeile 1?
    Du musst den Code zunächst korrekt in eine Klasse eines Projekts einfügen:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Net.Http;
    3. using System.Net.Http.Headers;
    4. using System.Windows.Forms;
    5. namespace WindowsFormsApp1
    6. {
    7. public partial class MainForm : Form
    8. {
    9. public MainForm()
    10. {
    11. this.InitializeComponent();
    12. }
    13. private async void Button1_Click(object sender, EventArgs e)
    14. {
    15. HttpClient client = new HttpClient();
    16. HttpRequestMessage request = new HttpRequestMessage
    17. {
    18. Method = HttpMethod.Post,
    19. RequestUri = new Uri("https://scrapesoft-music-lyrics.p.rapidapi.com/api/lyrics?access_token=%7BaccessToken%7D"),
    20. Headers =
    21. {
    22. { "X-RapidAPI-Key", "0814-4711" },
    23. { "X-RapidAPI-Host", "scrapesoft-music-lyrics.p.rapidapi.com" },
    24. },
    25. Content = new StringContent("{\n \"songName\": \"ENTER_SONG_NAME\",\n \"artistName\": \"ENTER_ARTIST_NAME\"\n}")
    26. {
    27. Headers =
    28. {
    29. ContentType = new MediaTypeHeaderValue("application/json")
    30. }
    31. }
    32. };
    33. using (HttpResponseMessage response = await client.SendAsync(request))
    34. {
    35. response.EnsureSuccessStatusCode();
    36. string body = await response.Content.ReadAsStringAsync();
    37. Console.WriteLine(body);
    38. }
    39. }
    40. }
    41. }
    Wenn ich den Code dann zeilenweise (!) ausführe (mit using), bekomme ich in Zeile 37 folgende Exception:

    "Not found", da musst Du selbst weiter machen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    Also, der Code oben funktioniert soweit.

    Du musst halt beachten, dass das using wie bei VB das Imports ist. Folgender Code funktioniert:

    C#-Quellcode

    1. using System;
    2. namespace Test {
    3. using System.Net.Http;
    4. using System.Net.Http.Headers;
    5. static class TestProgram {
    6. public static async Task Main(string[] args) {
    7. using var client = new HttpClient();
    8. using var request = new HttpRequestMessage {
    9. Method = HttpMethod.Post,
    10. RequestUri = new Uri("https://scrapesoft-music-lyrics.p.rapidapi.com/api/lyrics?access_token=%7B<accessToken>%7D"), // hier fehlt dein Access Token.
    11. Headers = {
    12. { "X-RapidAPI-Key", "5b562173eamshe210197d91f3862p11c919jsncef012d50a9a" }, // Lass das BITTE aus deinem Code!
    13. { "X-RapidAPI-Host", "scrapesoft-music-lyrics.p.rapidapi.com" }
    14. },
    15. Content = new StringContent(
    16. // JSON content
    17. """
    18. {
    19. "songName": "Walk Away From The Sun",
    20. "artistName": "Seether"
    21. }
    22. """
    23. ) {
    24. Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
    25. }
    26. };
    27. using var response = await client.SendAsync(request);
    28. Console.WriteLine($"Got response code { response.StatusCode }");
    29. var responseContent = await response.Content.ReadAsStringAsync();
    30. Console.WriteLine($"Got content: { responseContent }");
    31. }
    32. }
    33. }


    Leider muss ich dazu sagen, dass ich folgenden Output bekomme:

    Quellcode

    1. simon@ODIN: /home/simon/source/dotnet_tests/dotnet_tests
    2. ➜ ./bin/Debug/net8.0/dotnet_tests
    3. Got response code NotFound
    4. Got content: {"message":"Endpoint '\/api\/lyrics' does not exist"}​


    Ich weiß nicht, wo du den API-Endpunkt her hast, aber den gibt es scheinbar nicht.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    siycah schrieb:

    Ich weiß nicht, wo du den API-Endpunkt her hast, aber den gibt es scheinbar nicht.


    Ja der Code scheint zu funktionieren, aber das Ganze Ding scheint dauerhalft offline zu sein. Klicke mal hier auf "Test Endpoint".

    slice schrieb:

    Nach zwei drei Klicks auf deren Seite:


    Ja, dort empfehlen sie einem, auf die Projektwebsite zu gehen, aber hab keinen funktionierenden Link gefunden... (s.Anhang). Lasse mich aber gerne eines besseren belehren...
    Bilder
    • rapidapi screenshot.PNG

      184,1 kB, 1.920×1.030, 103 mal angesehen

    kafffee schrieb:

    Bei Spotify blick ich da nicht durch...


    Auf Spotify kannst du sowieso verzichten. Deren API ist eigentlich nicht für die Öffentlichkeit gedacht.
    Aber Musixmatch (wo Spotify auch seine Lyrics herholt) hat eine kostenlose API developer.musixmatch.com/plans

    ​track.lyrics.get?track_id=15953433

    Da musst du nur den WebRequest selbst zusammenbauen, aber die Doku scheint gut genug zu sein, dass man das recht schnell versteht.
    Wichtig ist nur, dass du bei denen scheinbar noch einen Tracker verwenden musst, vor allem wenn du Free User bist.

    Alternativ machst du das in deiner Anwendung konfigurierbar und siehst zu, dass deine User über den o.g. Link ein Konto erstellen und so an die Daten kommen.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.
    @siycah

    Cool danke das werd ich mir definitiv anschauen.

    Wenn man das "free" nutzt bekommt man aber nur 30% der Lyrics, also hab ich die jetzt mal angeschrieben, mal gespannt was sie mir für ein Angebot machen...

    Hab die Docs mal überflogen, ich denke das sollte ich hinbekommen, kann mich ja an dem Beispielcode hier im Thread halten.

    Ansonsten meld ich mich nochmal.

    Guten Rutsch :)

    kafffee schrieb:

    Wenn man das "free" nutzt bekommt man aber nur 30% der Lyrics, also hab ich die jetzt mal angeschrieben, mal gespannt was sie mir für ein Angebot machen...

    Verlass dich nicht darauf, dass sie dir ein (für Privatpersonen) gutes Angebot machen. Ich will nicht zu pessimistisch klingen, aber selbst bei mir als Kleinunternehme gibt's da Wucherpreise bei solchen vermeintlich "kleinen" Sachen.

    kafffee schrieb:

    Hab die Docs mal überflogen, ich denke das sollte ich hinbekommen, kann mich ja an dem Beispielcode hier im Thread halten.

    Genau, der Quellcode müsste nur entsprechend angepasst werden. Anstatt das JSON hart als String reinzuladen, würde ich dir empfehlen, dass mit einem JSON Objekt (Newtonsoft oder System.Text) zu machen. So vermeidest du kleine Fehler, die dir die Rübe zum Qualmen bringen. Trust me.

    kafffee schrieb:

    Guten Rutsch


    Danke, wünsche ich dir auch!
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    siycah schrieb:

    erlass dich nicht darauf, dass sie dir ein (für Privatpersonen) gutes Angebot machen. Ich will nicht zu pessimistisch klingen, aber selbst bei mir als Kleinunternehme gibt's da Wucherpreise bei solchen vermeintlich "kleinen" Sachen.


    Bin auf alles gefasst :)

    siycah schrieb:

    Anstatt das JSON hart als String reinzuladen, würde ich dir empfehlen, dass mit einem JSON Objekt (Newtonsoft oder System.Text) zu machen.


    Jou hatte ich sowieso vor :)
    Jetzt muss ich das Thema nochmal rauskramen, beim ursprünglichen Post hab ich s dann einfach mit dem WebClient gelöst.

    Und zwar hab ich mir grad meine erste eigene WebAPI zusammengeschustert, die zu funktionieren scheint

    Jetzt brauch ich nur noch die Klientanwendung machen...

    Ich hab jetzt Folgendes:

    VB.NET-Quellcode

    1. Private Sub btnRegistrierugAnfragen_Click(sender As Object, e As EventArgs) Handles btnRegistrierugAnfragen.Click
    2. Dim Data As New CustomerModel(1, txtEMail.Text, txtCustomerNo.Text, txtFingerPrint.Text, txtValidUntil.Text)
    3. RegistrierungAnfragen(Data)
    4. End Sub
    5. Public Shared Async Function RegistrierungAnfragen(argData As CustomerModel) As Task
    6. Using Client As HttpClient = New HttpClient
    7. Using Request = New HttpRequestMessage
    8. Request.Method = HttpMethod.Post
    9. Request.RequestUri = New Uri("https://localhost:7070/api/RegistrationDatas")
    10. Request.Headers.Add("accept", "text/plain")
    11. Request.Headers.Add("Content-Type", "application/json")
    12. Request.Content = New StringContent(JsonConvert.SerializeObject(argData))
    13. Using Response = Await Klient.SendAsync(Request)
    14. Dim RespnseContent = Await Response.Content.ReadAsStringAsync()
    15. Debug.WriteLine("Fertig!")
    16. End Using
    17. End Using
    18. End Using
    19. End Function


    Das Programm wirft keinen Fehler, aber die Ausführung kommt nie bis zu meinem Debug.Writeline. in der Ausgabe kommt das hier:

    Ausnahme ausgelöst: "System.InvalidOperationException" in System.Net.Http.dll

    Hat jemand ne Ahnung was da falsch ist? Ich vermute ja was mit den Headers.

    Schaut euch auch den Screenshot an, vielleicht hilft das
    Bilder
    • swagger.PNG

      94,29 kB, 1.920×1.030, 75 mal angesehen
    @siycah

    Hä? :)

    In Zeile 14 hab ich das doch oder?


    Edit @siycah
    Wie isses eigentlich hiermit?:

    VB.NET-Quellcode

    1. ​Request.Headers.Add("accept", "text/plain")
    2. Request.Headers.Add("Content-Type", "application/json")


    Da gibts doch sicherlich was "sichereres" als immer zwei Strings übergeben. Etwas mit IntelliSense-Unterstützung. Ich meine das irgendwo schon gesehen zu haben ?? Z.B. Post6, Zeile 30:

    C#-Quellcode

    1. Headers = { ContentType = new MediaTypeHeaderValue("application/json") }


    Ich habs nicht hinbekommen das nach VB zu übersetzen...

    Tatsache. Mein Fehler, habe ich wegen der Einrückung völlig übersehen. Das sieht aus, als wäre da dein Response-Block.

    Kannst du nochmal das JSON hier reinschreiben, was du übergibst?
    Und vielleicht auch die komplette Exception, inkl. Stacktrace?

    kafffee schrieb:

    Klient.SendAsync(Request)

    Zudem steht hier "Klient", ich kann aber nirgends eine solche Variable finden. Du hast wohl oben "Client" stehen. Schiebe ich mal auf Copy/Paste, weil der Code sonst nicht compilen würde.

    In deinem Content fehlt mir auch der MediaType, also "application/json".

    kafffee schrieb:

    Wie isses eigentlich hiermit?:


    Der erste Header passt. Der Zweite müsste eigentlich zum Content.

    kafffee schrieb:

    Da gibts doch sicherlich was "sichereres" als immer zwei Strings übergeben. Etwas mit IntelliSense-Unterstützung. Ich meine das irgendwo schon gesehen zu haben ?? Z.B. Post6, Zeile 30:


    So ist das nunmal mit dem HTTP(s) Protokoll. HTTP(s) basiert komplett auf String-Kommunikation.

    Du kannst z.B. auch über Telnet Daten von einem HTTP Server abrufen. Ist kein Hexenwerk:



    Ich wüsste jetzt nicht von irgendwelche Klassen, die die ganzen Types als Konstante vordefiniert hat.

    kafffee schrieb:

    Ich habs nicht hinbekommen das nach VB zu übersetzen...


    VB ist auch echt nicht meine Sprache. Viel zu kompliziert aufgebaut.

    Aber ich glaube, dass das so passen müsste:

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Net.Http
    3. Namespace Test
    4. Friend Module TestProgram
    5. Public Async Function Main(args As String()) As Task
    6. Dim client = New HttpClient()
    7. Dim request = New HttpRequestMessage With {
    8. .Method = HttpMethod.Post,
    9. .Content = New StringContent(
    10. """
    11. Dein JSON hier
    12. """,
    13. New Headers.MediaTypeHeaderValue("application/json")
    14. ),
    15. .RequestUri = New Uri("https://scrapesoft-music-lyrics.p.rapidapi.com/api/lyrics?access_token=%7B<accessToken>%7D") ' hier fehlt dein Access Token.
    16. }
    17. Dim response = Await client.SendAsync(request)
    18. Console.WriteLine($"Got response code {response.StatusCode}")
    19. Dim responseContent = Await response.Content.ReadAsStringAsync()
    20. Console.WriteLine($"Got content: {responseContent}")
    21. End Function
    22. End Module
    23. End Namespace
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „siycah“ ()

    siycah schrieb:

    Kannst du nochmal das JSON hier reinschreiben, was du übergibst?
    Und vielleicht auch die komplette Exception, inkl. Stacktrace?


    Mit StackTrace meinst du die Aufrufliste? Weil er wirft ja keine Exception, sondern gibt den Fehler nur in der Ausgabe aus, ohne das Programm anzuhalten.

    Ich bin das Programm mal in Einzelschritten durchgegangen. Ergebnis:

    Er springt mir direkt von Zeile 12 auf Zeile 19. Selbst wenn ich das hier in Zeile 13 mache überspringt er das einfach

    Dim JSONAnfrage As String = JsonConvert.SerializeObject(argData)

    Also hab ich s mal in Zeile 7 einngefügt. Hier das JSON:

    {"id":1,"email":"xxx@yyy.de","customerNo":"12345","fingerPrint":"abcdef","validUntil":"10.01.2024"}


    siycah schrieb:

    Du hast wohl oben "Client" stehen

    Yep, Tippfehler :)

    siycah schrieb:

    In deinem Content fehlt mir auch der MediaType, also "application/json".

    Was ist mit Zeile 12? Ist das falsch? Ich habe es leider nicht hinbekommen, das hier auf VB zu übersetzen:

    C#-Quellcode

    1. Headers = { ContentType = new MediaTypeHeaderValue("application/json") }



    Edit @siycah
    Okay, Stück weiter, hab jetzt das hier:

    VB.NET-Quellcode

    1. Request.Headers.Add("accept", "text/plain")
    2. Request.Content = New StringContent(JSONAnfrage, System.Text.Encoding.UTF8, "application/json")
    3. Using Response = Await Klient.SendAsync(Request)


    Da bekomm ich den JSON im Anhang als Antwort:
    Bilder
    • antwortcontent.PNG

      14,2 kB, 782×365, 71 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    Was ist mit Zeile 12? Ist das falsch? Ich habe es leider nicht hinbekommen, das hier auf VB zu übersetzen:


    Schau dir mal meine Änderung am Beitrag an. Das könnte dich schon weiterbringen.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems

    Selbstständiger Softwareentwickler & IT-Techniker.
    Warum benutzt du StringContent? Du könntest JsonContent benutzten, damit könntest du dir auch das setzten von dem Content-Type Header sparen.

    Edit: Oder direkt mit PostAsJsonAsync