7

Enter image description here

Enter image description here

I am testing a REST API post, and it works well when I try it on Postman. However, in some scenario (related to the posting XML data) if I post with HttpClient API, I would receive the following error:

Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

But the same XML content works fine on Postman with status OK and proper response.

What is the differences between using the C# HttpClient API and the postman testing? How can I configure my API call to match with the behavior on postman?

Here I attached the source code, and the Postman screenshot

public void createLoan()
{
    string baseCreateLoanUrl = @"https://serverhost/create?key=";
    var strUCDExport = XDocument.Load(@"C:\CreateLoan_testcase.xml");

    using (var client = new HttpClient())
    {
        var content = new StringContent(strUCDExport.ToString(), Encoding.UTF8, Mediatype);
        string createLoanApi = string.Concat(baseCreateLoanUrl, APIKey);

        try
        {
            var response = client.PostAsync(createLoanApi, content).Result;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error Happened here...");
            throw;
        }

        if (response.IsSuccessStatusCode)
        {
            // Access variables from the returned JSON object
            string responseString = response.Content.ReadAsStringAsync().Result;
            JObject jObj = JObject.Parse(responseString);

            if (jObj.SelectToken("failure") == null)
            {
                // First get the authToken
                string LoanID = jObj["loanStatus"]["id"].ToString();
                MessageBox.Show("Loan ID: " + LoanID);
            }
            else
            {
                string getTokenErrorMsg = string.Empty;

                JArray errorOjbs = (JArray) jObj["failure"]["errors"];
                foreach (var errorObj in errorOjbs)
                {
                    getTokenErrorMsg += errorObj["message"].ToString() + Environment.NewLine;
                }
                getTokenErrorMsg.Dump();
            }
        }
    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mting923
  • 431
  • 1
  • 6
  • 15
  • can u add your contract (interface) on ur post ? – ahankendi Dec 13 '16 at 19:44
  • Sorry @ahankendi , unfortunately, I don't have access to the server side api. – mting923 Dec 13 '16 at 19:50
  • Although It probbably doesn't have much to do with your issue, please stop using .Result and start using await instead. .Result will block your thread and can cause a deadlock if you are not being careful. I would suggest learning how to work with async/await, which will make your life so much easier. :) – Kerim Emurla Dec 13 '16 at 20:46
  • Thanks for your comment, Kerim. I actually tried everything including async/await and even singleton like Nard suggested below before but they all return the same error. – mting923 Dec 13 '16 at 22:18
  • In case someone else stumbles upon this question, what fixed my problem was setting the allowed security protocol: System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; courtesy of: https://stackoverflow.com/a/46223433/1243268 – RdPC Aug 29 '19 at 12:49

3 Answers3

5

Thanks for Nard's comment, after comparing the header, I found the issue my client header has this: Expect: 100-continue

While postman doesn't has.

Once I removed this by using the ServicePointManager:

ServicePointManager.Expect100Continue = false;

Everything seems fine now. Thanks all the input!

mting923
  • 431
  • 1
  • 6
  • 15
3

My gut tells me it's something simple. First, we know the API works, so I'm thinking it's down to how you are using the HttpClient.

First things first, try as suggested by this SO answer, creating it as a singleton and drop the using statement altogether since the consensus is that HttpClient doesn't need to be disposed:

    private static readonly HttpClient HttpClient = new HttpClient();

I would think it would be either there or an issue with your content encoding line that is causing issues with the API. Is there something you are missing that it doesn't like, I bet there is a difference in the requests in Postman vs here. Maybe try sending it as JSON ala:

     var json = JsonConvert.SerializeObject(strUCDExport.ToString());
     var content = new StringContent(json, Encoding.UTF8, Mediatype);

Maybe the header from Postman vs yours will show something missing, I think the real answer will be there. Have fiddler running in the background, send it via Postman, check it, then run your code and recheck. Pay close attention to all the attribute tags on the header from Postman, the API works so something is missing. Fiddler will tell you.

Community
  • 1
  • 1
Nard Dog
  • 906
  • 1
  • 18
  • 33
  • Thanks Nard for your detailed suggestion. However, now when I haved the fiddler running aside. I don't have the error as before, instead I got the "A loan already exists with the Loan Number: "1612EM000064", which sounds like the api has two shots and I got the 2nd response... why does fiddler would cause this? – mting923 Dec 13 '16 at 21:44
  • resolved after comparing the header line by line using fiddler, removing "Expect: 100-continue" did the work. Check my own post for details. – mting923 Dec 13 '16 at 22:38
-1

I was struggling with this for 2 days when I stumbled over Fiddler which lets you record the traffic to the service. After comparing the calls I saw that I had missed a header in my code.

Petter Ivarsson
  • 463
  • 6
  • 6