none
ASP.NET CORE CONSOLE APP | httpclient post endet in 400 Fehler RRS feed

  • Frage

  • Hallo zusammen,

    leider erhalte ich bei Aufruf der Lexoffice API folgenden Fehler:

    URL: https://api.lexoffice.io/v1/invoices/?finalize=false
    Output: { "timestamp" : "2020-08-09T13:22:49.531+02:00", "status" : 400, "error" : "Bad Request", "path": "/v1/invoices/", "traceId": "34abdd266416", "message": "The request is badly malformed and could not be read."  }

    Hier nun mein Code:

    string smaDate = DateTime.Now.ToString("yyyy-MM-ddTHH':'mm':'sszzz"); string smaRechnungJson = $@"{{""archived"": false, ""voucherDate"": ""{smaDate}"", ""address"": {{ ""name"": ""Bike & Ride GmbH & Co. KG"", ""supplement"": ""Gebäude 10"", ""street"": ""Musterstraße 42"", ""city"": ""Freiburg"", ""zip"": ""79112"", ""countryCode"": ""DE"" }}, ""lineItems"": [ {{ ""type"": ""custom"", ""name"": ""TestProdukt"", ""quantity"": 1, ""unitName"": ""Stück"", ""unitPrice"": {{ ""currency"": ""EUR"", ""grossAmount"": 1.99, ""taxRatePercentage"": 19 }}, ""discountPercentage"": 0 }}, {{ ""type"": ""text"", ""name"": ""Strukturieren Sie Ihre Belege durch Text-Elemente."", ""description"": ""Das hilft beim Verständnis"" }} ], ""totalPrice"": {{ ""currency"": ""EUR"", ""totalGrossAmount"": 1.99 }}, ""taxConditions"": {{ ""taxType"": ""net"" }}, ""paymentConditions"": {{ ""paymentTermLabel"": ""sofort, ohne Abzug"", ""paymentTermDuration"": 0, ""paymentDiscountConditions"": {{ ""discountPercentage"": 0, ""discountRange"": 0 }} }}, ""shippingConditions"": {{ ""shippingDate"": ""{smaDate}"", ""shippingType"": ""delivery"" }}, ""title"": ""Rechnung"", ""introduction"": ""Ihre bestellten Positionen stellen wir Ihnen hiermit in Rechnung"", ""remark"": ""Vielen Dank für Ihren Einkauf"" }}";

    var buffer = System.Text.Encoding.UTF8.GetBytes(smaRechnungJson); var byteContent = new ByteArrayContent(buffer); byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var builder = new UriBuilder("https://api.lexoffice.io/v1/invoices/"); builder.Port = -1; var query = HttpUtility.ParseQueryString(builder.Query); query["finalize"] = "false"; builder.Query = query.ToString(); string url = builder.ToString(); Console.WriteLine("URL: " + url); client.DefaultRequestHeaders.Add("Accept", "application/json"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "hier mein token"); var response = await client.PostAsync(url, byteContent); var responseString = await response.Content.ReadAsStringAsync(); Console.WriteLine("Response: " + responseString);


    Ich hoffe jemand hat eine Idee was ich falsch mache.

    Ein schönes Restwochenende wünsche ich allen.

    Grüße

    Sven

    Sonntag, 9. August 2020 11:34

Antworten

  • Hallo Sven,

    das Datum hab ich mir zwar angeschaut aber der Unterschied ist mir irgendwie entgangen. Allerdings muss ich gestehen, dass ich dem geforderten Format für diese Zwecke nicht wirklich was abgewinnen und ehrlich gesagt auch nicht verstehen kann, warum das als malformed request abgelehnt wird.

    Nichts desto trotz:

    DateTime.Now.ToString( "yyyy-MM-ddTHH:mm:ss.fffzzz" )


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    • Bearbeitet Stefan FalzModerator Dienstag, 11. August 2020 20:20
    • Als Antwort markiert sm-a Dienstag, 11. August 2020 21:15
    Dienstag, 11. August 2020 20:18
    Moderator

Alle Antworten

  • Hallo Sven,

    poste doch mal bitte exakt den String, der zur Laufzeit nach der Zuweisung in smaRechnungJson steht.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    Montag, 10. August 2020 08:06
    Moderator
  • Hallo Stefan,

    hier nun den String (smaRechnungJson) wie er an Lexoffice zur Laufzeit übermittelt wird:

    {"archived": false,
        "voucherDate": "2020-08-10T19:06:59+02:00",
        "address": {
            "name": "Bike & Ride GmbH & Co. KG",
            "supplement": "Gebäude 10",
            "street": "Musterstraße 42",
            "city": "Freiburg",
            "zip": "79112",
            "countryCode": "DE"
        },
        "lineItems": [
            {
                "type": "custom",
                "name": "TestProdukt",
                "quantity": 1,
                "unitName": "Stück",
                "unitPrice": {
                    "currency": "EUR",
                    "grossAmount": 1.99,
                    "taxRatePercentage": 19
                },
                "discountPercentage": 0
            },
            {
                "type": "text",
                "name": "Strukturieren Sie Ihre Belege durch Text-Elemente.",
                "description": "Das hilft beim Verständnis"
            }
        ],
        "totalPrice": {
            "currency": "EUR",
            "totalGrossAmount": 1.99
        },
        "taxConditions": {
            "taxType": "net"
        },
        "paymentConditions": {
            "paymentTermLabel": "sofort, ohne Abzug",
            "paymentTermDuration": 0,
            "paymentDiscountConditions": {
                "discountPercentage": 0,
                "discountRange": 0
            }
        },
        "shippingConditions": {
            "shippingDate": "2020-08-10T19:06:59+02:00",
            "shippingType": "delivery"
        },
        "title": "Rechnung",
        "introduction": "Ihre bestellten Positionen stellen wir Ihnen hiermit in Rechnung",
        "remark": "Vielen Dank für Ihren Einkauf"
    }


    Ich hoffe Du oder ein anderer findet die Lösung - bin echt ratlos.

    Montag, 10. August 2020 17:09
  • Hier nochmals an alle den Link zur API Dokumentation von Lexoffice um meinen Fehler zu finden:

    https://developers.lexoffice.io/docs/#invoices-endpoint-create-an-invoice

    Gruß
    Sven

    Montag, 10. August 2020 17:12
  • Hallo Sven,

    gehen wir das mal Schritt für Schritt durch. Lt. Doku soll der Url wie folgt lauten:

      https://api.lexoffice.io/v1/invoices?finalize=true

    Deiner lautet aber:

      https://api.lexoffice.io/v1/invoices/?finalize=true

    Ändere das mal bei dir (lass also den abschließenden / nach "invoices" weg.

    Dann hab ich das Ganze mal etwas vereinfacht, da mir dein Weg zu kompliziert war. Mangels Login zur API kann ich das nicht selbst testen (kommt verständlicherweise ein unauthorized Fehler zurück), probier es bitte mal.

    Deinen JSON Inhalt hab ich der Einfachheit halber in eine Datei gesteckt, das kannst Du ggfs. auch mal tun, das hält den Code fürs testen kleiner.

    Ein Unterschied zu deinem Code ist, dass ich StringContent und nicht ByteArrayContent verwende. JSON ist letztendlich nur ein String, daher kann man das IMHO ruhig auch so machen.

    using System;
    using System.IO;
    using System.Text;
    using System.Net.Http;
    
    namespace Test
    {
        class Program
        {
    
            static HttpClient _httpClient;
    
            static void Main( string[] args )
            {
                _httpClient = new HttpClient();
    
                string url = "https://api.lexoffice.io/v1/invoices?finalize=false";
                string body = File.ReadAllText( @"X:\Ordner\sm-a.json", Encoding.UTF8 );
    
                 HttpRequestMessage request = new HttpRequestMessage( HttpMethod.Post, url ) {
                    Content = new StringContent( body, Encoding.UTF8, "application/json" )
                };
    
                request.Headers.Add( "Authorization", "Bearer {accessToken}" );
                request.Headers.Add( "Accept", "application/json" );
                request.Method = HttpMethod.Post;
    
                HttpResponseMessage response = _httpClient.SendAsync( request ).Result;
    
                String jsonResult = response.Content.ReadAsStringAsync().Result;
    
                Console.WriteLine( jsonResult );
            }
        }
    }


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport



    Montag, 10. August 2020 22:08
    Moderator
  • Hallo Stefan,

    leider funktioniert es immer noch nicht. Ich habe an Deinem Code nur den Token und den FilePath geändert. Ich erhalte folgende immer noch folgende Fehlermeldung:

     { "timestamp" : "2020-08-11T21:06:27.755+02:00", "status" : 400, "error" : "Bad Request", "path": "/v1/invoices", "traceId": "b5939d717788", "message": "The request is badly malformed and could not be read."  }

    Auch das habe ich beachtet:

    https://api.lexoffice.io/v1/invoices?finalize=true

    Würde mich freuen wenn Du oder ein anderer eine Idee hat warum es nicht funktioniert.

    Gruß

    Sven


    • Bearbeitet sm-a Dienstag, 11. August 2020 19:09
    Dienstag, 11. August 2020 19:09
  • Hallo Sven,

    probier es dann bitte mal mit exakt dem JSON String, der hier zu finden ist:

      https://developers.lexoffice.io/docs/#invoices-endpoint-create-an-invoice

    Wenn es auch mit dem nicht klappt, kontaktier bitte den Support und teil denen mit, dass ihre API wohl einen Fehler hat oder in der Dokumentation etwas fehlt.

    Da ich kein Token habe, kann ich das leider selbst nicht testen.

    Wenn Du eines für reine Testzwecke hast, kannst Du mir das ggfs. auch per Email mitteilen (für eine Sandbox oder ähnliches). Ein produktives bitte nicht, das macht wenig Sinn.

    ---

    BTW: Ich hatte in meinem Code auch noch invoices/?... stehen, sorry. Der Slash sollte da natürlich auch weg.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport



    Dienstag, 11. August 2020 19:25
    Moderator
  • Hallo Stefan,

    habe gleich das Beispiel von Lexoffice wie Du vorgeschlagen hast getestet. Das hat funktioniert.

    Daher habe ich gleich nachgesehen was anders ist und da viel mir das Datum auf.

    Ich habe:

    2020-08-10T19:06:59+02:00

    Lexoffice hat im Beispiel:

    2017-04-22T00:00:00.000+02:00

    Hier nun das komplette Beispiel das funktioniert hat:

    {
      "archived": false,
      "voucherDate": "2020-08-11T00:00:00.000+02:00",
      "address": {
        "name": "Bike & Ride GmbH & Co. KG",
        "supplement": "Gebäude 10",
        "street": "Musterstraße 42",
        "city": "Freiburg",
        "zip": "79112",
        "countryCode": "DE"
      },
      "lineItems": [
        {
          "type": "custom",
          "name": "Energieriegel Testpaket",
          "quantity": 1,
          "unitName": "Stück",
          "unitPrice": {
            "currency": "EUR",
            "netAmount": 5,
            "taxRatePercentage": 0
          },
          "discountPercentage": 0
        },
        {
          "type": "text",
          "name": "Strukturieren Sie Ihre Belege durch Text-Elemente.",
          "description": "Das hilft beim Verständnis"
        }
      ],
      "totalPrice": {
        "currency": "EUR"
      },
      "taxConditions": {
        "taxType": "net"
      },
      "paymentConditions": {
        "paymentTermLabel": "sofort, ohne Abzug",
        "paymentTermDuration": 0,
        "paymentDiscountConditions": {
          "discountPercentage": 0,
          "discountRange": 0
        }
      },
      "shippingConditions": {
        "shippingDate": "2020-08-11T00:00:00.000+02:00",
        "shippingType": "delivery"
      },
      "title": "Rechnung",
      "introduction": "Ihre bestellten Positionen stellen wir Ihnen hiermit in Rechnung",
      "remark": "Vielen Dank für Ihren Einkauf"
    }

    Wie muss ich die folgende Code Zeile anpassen damit ich das "shippingDate" im Format des obigen Beispiels erhalte?

     DateTime.Now.ToString("yyyy-MM-ddTHH':'mm':'sszzz");

    Vielen Dank für Deine Hilfe.

    Gruß

    Sven

    Dienstag, 11. August 2020 20:04
  • Hallo Sven,

    das Datum hab ich mir zwar angeschaut aber der Unterschied ist mir irgendwie entgangen. Allerdings muss ich gestehen, dass ich dem geforderten Format für diese Zwecke nicht wirklich was abgewinnen und ehrlich gesagt auch nicht verstehen kann, warum das als malformed request abgelehnt wird.

    Nichts desto trotz:

    DateTime.Now.ToString( "yyyy-MM-ddTHH:mm:ss.fffzzz" )


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport


    • Bearbeitet Stefan FalzModerator Dienstag, 11. August 2020 20:20
    • Als Antwort markiert sm-a Dienstag, 11. August 2020 21:15
    Dienstag, 11. August 2020 20:18
    Moderator
  • Hallo Stefan,

    kaum habe ich den DateTime Parameter auf deinen geändert und schon funktioniert es. Ist schon komisch aber Hauptsache es geht nun.

    Vielen vielen Dank.

    Gruß
    Sven

    Dienstag, 11. August 2020 21:15