differences between using C# HttpClient api and th

2019-06-20 14:49发布

问题:

I am testing a rest API post, 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.

Anyone know what is the differences between using 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();
            }
        }           
}

Thanks!!!

回答1:

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.



回答2:

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!