Wow, it’s been a while…

I’ve been testing the REST API for Salesforce’s Radian6.  It’s very straightforward, but I spent HOURS trying to get it to work in .NET (C#).  I thought that it made sense to further document it here, and hopefully up the Google hit count.

Making a REST call in .NET is a no-brainer.  Simple code like the following should do the trick:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
protected string Call_Rest()
{
    //REST call:
    using (WebClient client = new WebClient())
    {
        //add HTTP headers (for auth)
        client.Headers.Add("auth_appkey", auth_appkey);
        if (auth_token == null || auth_token.Trim() == "")
        {
            client.Headers.Add("auth_user", auth_user);
            client.Headers.Add("auth_pass", auth_pass);
        }
        else
        {
            client.Headers.Add("auth_token", auth_token);
        }

        //send web request; get web response as XML
        try
        {
            responseXml = client.DownloadString(url);
        }
        catch (Exception exc)
        {
            responseXml = "ERROR: " + exc.Message;
        }
    }

    return responseXml;
}

 

The problem, of course, is that despite Googling for the syntax of making REST calls, and whether I used .NET’s WebClient, HttpWebRequest, or WebRequest classes, I kept on getting the same failure: a hang of a few minutes, followed by .NET throwing an exception with the message: “The underlying connection was closed: An unexpected error occurred on a send.”

This told me little, and pissed me off, and I was trying things left and right for at least 5 hours to no avail.  What made it even crazier is that when I used RESTClient (as suggested by Radian6 support), I had zero problems connecting to the Radian6 API.  So it was clearly something that I had to do in .NET to make this work.  But what?  

I only found the solution on my fourth page of Google results, on a post that is over 4 1/2 years old.  It turns out that:

“…the defult behavior in Vista and Server 2008 is to use TLS first for secure connections. If the server doesn’t support TLS, it’s supposed to negotiate with the client to use SSL3. In this case, the remote server wasn’t negotiating at all…It was just dropping the connection.”

So clearly, the Radian6 servers are using SSL, my code was using TLS by default, and the Radian6 server does not renegotiate to use SSL.  So the solution is merely to include the following ONE line of code, before the WebClient (or WebRequest or HttpWebRequest) is instantiated (so before line 3 in the code above).  And that line of code is:

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

 

That’s it.  So simple, yet so impossible to find documented anywhere. Even 4 1/2 years after this post. Sheesh.  Microsoft.

 

22 Responses to REST calls in .NET (C#) over SSL (HTTPS)

  1. Jan Dolejs says:

    You have just saved my day…
    I have spent like 4 hours before i found your post.
    Thanks!

  2. Sergey Frolov says:

    Big respect to you, you saved me too 🙂
    Below – error descriptions on English and Russian, maybe this will help others to find this post.
    ps: i’m using VB.Net Webclient()

    System.Net.WebException: “The underlying connection was closed: An unexpected error occurred on a send.”
    System.IO.IOException: “Authentication failed because the remote party has closed the transport stream.”

    System.Net.WebException: “Базовое соединение закрыто: Непредвиденная ошибка при передаче.”
    System.IO.IOException: “Проверка подлинности не пройдена из-за закрытия транспортного потока удаленной стороной.”

  3. Anthony says:

    Thank you, thank you, thank you! I had been connecting to regular http rest api’s for several different websites without any issue, then I went and connected to one that was https instead, and kept getting the time you mentioned. Thank you for pointing this out, and helping me resolve my issue!

    For it to work in VB, all I had to do was drop the ; at the end of the single line example.

  4. Rima says:

    Hey dude,

    You saved my times. Thanks for this great post.

  5. Mitch says:

    YAY AVIV! Grrrr Microsoft!

    You have just saved me HOURS of work!

    Thanks man!

  6. Roshh says:

    Thanks a lot, sir.
    Been working for 3 hours before I found this treasure.
    Wish I could treat you with a beer!

  7. prteek Saluja says:

    one of the best answer man. 100 % correct.
    It save my time.
    Thanks

  8. Jason Frank says:

    You sir are a prince among men, a prince. How can this be so under documented when it is so necessary!?!

    Anyway, you saved my sanity and I thank you for that.

  9. […] connection before authentication could occur.  After 2 days of researching on and off, I found this.  The Kemp Load Balancer uses SSL3 but .Net always starts with TLS.  AH HAA.  The .Net to […]

  10. Nic says:

    Thank you! You are great!

  11. Joe says:

    Sweet! Very helpful, thanks.

  12. Chris Knight says:

    Unbelievable! I have been banging my head against the wall. Thank you so much!

  13. Anand says:

    This is my code:

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(“myurl”);

    request.Method = “POST”;
    request.KeepAlive = false;
    request.ContentType = “application/x-www-form-urlencoded”;
    request.UserAgent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; CK={CVxk71YSfgiE6+6P6ftT7lWzblrdvMbRqavYf/6OcMIH8wfE6iK7TNkcwFAsxeChX7qRAlQhvPWso3KI6Jthvnvls9scl+OnAEhsgv+tuvs=}; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”;
    int pos = Request.Url.AbsoluteUri.LastIndexOf(‘/’);

    // PAYMENT RESPONSE PAGE
    string strURL = Request.Url.AbsoluteUri.Substring(0, pos + 1) + “xxx.aspx”;

    string postData = “custacc=1234567890&login=” + ATOMLogin + “&pass=” + ATOMPassword”;

    byte[] byteArray = Encoding.UTF8.GetBytes(postData);

    request.ContentType = “application/x-www-form-urlencoded”;

    request.ContentLength = byteArray.Length;
    request.AllowAutoRedirect = true;

    request.Proxy.Credentials = CredentialCache.DefaultCredentials;

    Stream dataStream = request.GetRequestStream();

    dataStream.Write(byteArray, 0, byteArray.Length);

    dataStream.Close();

    WebResponse response = request.GetResponse();

    Still am getting Same Erro. pls help me
    Error: The underlying connection was closed: An unexpected error occurred on a send.

    • Ron says:

      ..did you ever figure this out?… despite other saying the above article helped them.. I’m not having any such luck.

      HELP!

  14. Anuj says:

    This works for me..
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;

  15. Alisettar says:

    Thanks a lot. It solved my problem. But with a little correction. In my case i used not SecurityProtocolType.Ssl3 but SecurityProtocolType.Tls12

  16. one developer says:

    WOW,
    This line was very helpfull!
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;

    Thanks!

    • FloatingCloud says:

      Thanks Aviv! SecurityProtocolType.Ssl3; worked for me.
      SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls; did not work.

  17. Mary says:

    Thank you so much! This save me oodles of time.

  18. dotnetrocks says:

    THANK YOU SO MUCH!! Found this after wasting hours to make a simple REST call work and your article did the trick!!

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;

    Just a note as lot of orgs are disabling TLS1.0 adding TLS12 did the magic for me – thanks again!!

  19. ThankYouAll says:

    Thank you all, this helped tremendously. Adding more info for others:

    SSIS WebClient errors “Authentication failed because the remote party has closed the transport stream” and “The underlying connection was closed: An unexpected error occurred on a send.”

    What helped me solve this issue after many hours of searching was this line (place it right before you create your webclient)

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;

    For some reason just the .Tls would not work correctly.

Leave a Reply

Your email address will not be published. Required fields are marked *

Set your Twitter account name in your settings to use the TwitterBar Section.