Bad Request on POST to Account

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • suchja
    Junior Member
    • Oct 2020
    • 5

    Bad Request on POST to Account

    Dear all,

    in my attempt to update data in Espo via the API from a C# application I only get Bad Request as response. After hours of trying I started to implement a simple example based on the API documentation and that also doesn't work.

    This is what I'm doing in my (C#) code:
    Code:
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri(URL);
    
    // Add an Accept header for JSON format.
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Add("X-Api-Key", apiKey);
    
    var payload = "{\"name\":\"AnotherCustomer\", \"type\":\"Customer\"}";
    var kundenUrl = "api/v1/Account";
    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    
    HttpResponseMessage resposne = client.PostAsync(kundenUrl, content).Result;
    This is the generated Request

    Request: Method: POST, RequestUri: 'http://myespo.org/api/v1/Account', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
    {
    Accept: application/json
    X-Api-Key: aab35cf80b4e9f4a2522855c2ff359e6
    Content-Type: application/json; charset=utf-8
    Content-Length: 48
    }

    The answer is a simple 400 - Bad Request without any further information. I checked the log and it shows the following:
    [2020-xxxxxxx] Espo.ERROR: (400) POST /Account; line: 81, file: /var/www/html/application/Espo/Core/Controllers/Record.php [] []

    Any ideas what is going wrong?

    Best regards
    Jan

    PS: GET works fine and thus I would assume that authentication is not an issue.
  • suchja
    Junior Member
    • Oct 2020
    • 5

    #2
    RESOLVED!

    The problem was Content-Type: application/json; charset=utf8. While application/json is obviously required, the automatically added charset=utf8 was not accepted by Espo. At least the HttpClient class in .NET 5 (and probably below) automatically adds the charset into the Content-Type. It looks like the only solution is to manually remove the complete Content-Type and add it again with only application/json. So my final working code looks like this:

    Code:
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri(URL);
    
    // Add an Accept header for JSON format.
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    client.DefaultRequestHeaders.Add("X-Api-Key", apiKey);
    
    var payload = "{\"name\":\"AnotherCustomer\", \"type\":\"Customer\"}";
    var kundenUrl = "api/v1/Account";
    var content = new StringContent(payload, Encoding.UTF8, "application/json");
    
    [B]// remove all content-type information and only add the required one again!
    content.Headers.Remove("Content-Type"); // "{application/json; charset=utf-8}"
    content.Headers.Add("Content-Type", "application/json");[/B]
    
    HttpResponseMessage resposne = await client.PostAsync(kundenUrl, content);

    Comment


    • telecastg
      telecastg commented
      Editing a comment
      Kudos for posting the solution !

    • yaronoz
      yaronoz commented
      Editing a comment
      Hi I've tried using this code but I keep getting the following error:

      AuthenticationException: Authentication failed because the remote party sent a TLS alert: 'HandshakeFailure'.

      this is my code:

      ServicePointManager.ServerCertificateValidationCal lback += (sender, cert, chain, sslPolicyErrors) => true;

      var handler = new HttpClientHandler()
      {
      SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls,
      ClientCertificateOptions = ClientCertificateOption.Automatic
      };



      var client = new HttpClient(handler);

      string apiKey = "api_key";


      client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");


      client.BaseAddress = new Uri("https://myespo.com");

      // Add an Accept header for JSON format.
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
      client.DefaultRequestHeaders.Add("X-Api-Key", apiKey);

      var payload = "{"name":"AnotherCustomer", "type":"Customer"}";
      var kundenUrl = "api/v1/Account";
      var content = new StringContent(payload, Encoding.UTF8, "application/json");

      // remove all content-type information and only add the required one again!
      content.Headers.Remove("Content-Type"); // "{application/json; charset=utf-8}"
      content.Headers.Add("Content-Type", "application/json");

      HttpResponseMessage resposne = await client.PostAsync(kundenUrl, content);

      what am I doing wrong?
Working...