0

I'm trying to POST a xml body to an api. this is what I have.


private HttpClient _client;
private HttpResponseMessage BaseHttpCallForStringData(string authorizationString, string targetUrl, string method, string contentType, string data)
        {
            logger.LogInformation("BaseHttpCall: " + "start");
            response = null;

            _client.DefaultRequestHeaders.Clear();
            if (!string.IsNullOrEmpty(contentType))
            {
                _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
            }

            logger.LogInformation("Calling service: " + targetUrl);

            if (authorizationString != null)
            {
                _client.DefaultRequestHeaders.Add("X-API-KEY", authorizationString);
            }

            try
            {
                HttpContent _Body = new StringContent("");
                if (!string.IsNullOrEmpty(contentType))
                {
                  _Body.Headers.ContentType = new MediaTypeHeaderValue(contentType);
                }

                if (data != null)
                {
                   string objData = data;
                   _Body = new StringContent(objData);
                }
                response = _client.PostAsync(targetUrl, _Body).Result;
            }
            catch (Exception e)
            {
                response = null;
                logger.LogError("Error: " + e.StackTrace);
                logger.LogError("Log E: ");
                logger.LogError(null, e, "error");
            }

            return response;
        }

Double checked the API-KEY, username and password for the api. They are correct. Tried in Postman, returns status 200. I'm kinda confused which one of credentials are wrong, as they all have the correct values when debugging. Thanks for helping guys.

Edit#1

POST https://api30-3.infinite-convergence.com/soap: {
  "Network": {
    "addresses": {
      "local": {
        "address": "192.168.10.142",
        "family": "IPv4",
        "port": 55555
      },
      "remote": {
        "address": "52.194.115.221",
        "family": "IPv4",
        "port": 443
      }
    },
    "tls": {
      "reused": false,
      "authorized": true,
      "authorizationError": null,
      "cipher": {
        "name": "ECDHE-RSA-AES128-GCM-SHA256",
        "standardName": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
        "version": "TLSv1/SSLv3"
      },
      "protocol": "TLSv1.2",
      "ephemeralKeyInfo": {},
      "peerCertificate": {
        "subject": {
          "commonName": "*.infinite-convergence.com",
          "alternativeNames": "DNS:*.infinite-convergence.com, DNS:infinite-convergence.com"
        },
        "issuer": {
          "country": "GB",
          "stateOrProvince": "Greater Manchester",
          "locality": "Salford",
          "organization": "Sectigo Limited",
          "commonName": "Sectigo RSA Domain Validation Secure Server CA"
        },
        "validFrom": "May 10 00:00:00 2022 GMT",
        "validTo": "Jun 10 23:59:59 2023 GMT",
        "fingerprint": "3F:44:D6:C8:EC:42:05:E9:EE:8F:72:4B:1D:D3:49:7A:7E:31:B1:F8",
        "serialNumber": "850bed13e44777cce777b77779bafee5"
      }
    }
  },
  "Request Headers": {
    "x-api-key": "API Key same as the c# code",
    "cache-control": "no-cache",
    "postman-token": "def36a21-c850-4a7f-8b03-e7c11ee135b4",
    "host": "api30-3.infinite-convergence.com",
    "content-length": "877"
  },
  "Request Body": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \r\nxmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \r\nxmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" \r\nxmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n<soap:Body soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n<SendSMS xmlns=\"http://infinite.com/sms\">\r\n<authid xsi:type=\"xsd:string\">same as well</authid>\r\n<authcode xsi:type=\"xsd:string\">same</authcode>\r\n<fieldcodes xsi:type=\"xsd:string\">{name},%time,%code</fieldcodes>\r\n<!-- <source xsi:type=\"xsd:string\">123456</source> -->\r\n<destination xsi:type=\"xsd:string\">\r\n6590891828;j; 1234;\r\n6592289062;e\r\n</destination>\r\n<message xsi:type=\"xsd:string\">Hi {name}, your order is ready for %time\r\npickup. Use code 6354 for quicker service. </message>\r\n</SendSMS>\r\n</soap:Body>\r\n</soap:Envelope>",
  "Response Headers": {
    "date": "Sat, 28 May 2022 02:28:56 GMT",
    "content-type": "text/xml; charset=utf-8",
    "content-length": "608",
    "connection": "keep-alive",
    "server": "Apache"
  },
  "Response Body": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:tns=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:types=\"http://infinite.com/sms//encodedTypes\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n<soap:Body soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n<SendSMSResponse xmlns=\"http://infinite.com/sms\">\n<SendSMSResult xsi:type=\"xsd:string\">success</SendSMSResult>\n</SendSMSResponse>\n</soap:Body>\n</soap:Envelope>\n"
}

Solution
Used a string instead of using a StringBuilder. Will try to figure out why this happens and update on this question again.

Bruce
  • 49
  • 7
  • 1
    It will be fastest to look at the request generated by C# and compare it to a request generated by/ used in postman. The difference will explain how your code is not generating a working call – Caius Jard May 28 '22 at 03:18
  • Show us a raw working request in postman and show us a screenshot of the debugger giving the value of your auth variable. Alternatively show us a wire shark or fiddler (don't forget to set fiddler as the proxy for the request in c#/postman) trace screenshot of the C# request versus a wire shark of the postman request – Caius Jard May 28 '22 at 03:22
  • @CaiusJard, I did compare those 2 request body, they looks rather Identical. Not sure how can I let you test without the api-key and other credentials – Bruce May 28 '22 at 03:30
  • It probably won't be the body, it will be the headers. They aren't identical; most likely the Authorization header coming out of the C# is not acceptable/formatted compared to the postman. I just want to see screen shots of the request headers but if you're concerned about security you can blank out some part of the api key that is absolutely identical in both. Do not, however, blank out any difference. For example if the c# looks like `API-KEY 123456789asdfghkl` and the postman looks like `API-KEY "123456789asdfghkl"` don't post a redaction of `API-KEY ##########` for both, but feel free to – Caius Jard May 28 '22 at 03:37
  • Post a redaction of `API-KEY 123##########hkl` for the c# and `API-KEY "123##########hkl"` for the postman, as a critical difference (the quote marks) is still visible – Caius Jard May 28 '22 at 03:38
  • @CaiusJard, I actually have another Post with 'text/plain' with is calling the same api (same credentials), it works. Not sure why it didn't work on this (POST XML). – Bruce May 28 '22 at 03:41
  • @CaiusJard, also there are credentials in the XML Body as well. So naturally, I will assume is the XML body did not parsed properly. – Bruce May 28 '22 at 03:44
  • Perhaps, if the server is parsing the body, reading the creds using them and failing then returning a 401. A server could be badly coded to look at the user agent and if it's not IE6, return a 401.. But let's go for the simple win first and compare a working with non working request; same "you can redact any parts of a credential that are guaranteed identical in both" applies. If everything checks out with every auth then we can start to look at other differences like changing the media type in postman and see if it result in a 401 – Caius Jard May 28 '22 at 03:50
  • @CaiusJard, surprisingly even changing the data type to JSON in Postman will return a status 200... – Bruce May 28 '22 at 05:44
  • The other reason I asked for screenshots is because I can then see what you see, in a presentation I'm familiar with because I(we) debug scenarios like this a lot. You providing just one side of the comparison, in some JSON and saying "I promise the other side is the same" a) isn't helpful and b) cannot be true because if the two requests were the same then they would both work. As a small tip for stackoverflow, if someone demonstrates interest in helping you asks for X, Y and Z, give them what they ask for rather than W. Make yourself easy to help; there are way more questions than answerers – Caius Jard May 28 '22 at 07:16
  • @CaiusJard, Okay you have your points there. So How can I provide more information about it? – Bruce May 29 '22 at 14:37
  • We need to get some way of looking at exactly what c# sends; you can take a look at https://stackoverflow.com/questions/18924996/logging-request-response-messages-when-using-httpclient for tracing http client, or you could install Fiddler and configure your c# to use it as a proxy (but needs a bit of messing to decrypt https); you could install wireshark and just have it pick up the TCP packets and re-form them into an HTTP (not https) conversation. Once you have the raw request data http client is sending then we can compare these with the raw request that works in postman.. – Caius Jard May 30 '22 at 05:36
  • @CaiusJard Hi Caius, I have solved the issue by comparing the visual studio C# and Postman C# -Restsharp. The issue lies in I was using a StringBuilder for the XMLBody, so I just convert it into just a string solves the whole issue. – Bruce May 30 '22 at 08:48

0 Answers0