Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

https request fails only in .net web app

I am trying to patch a .net web application that after years of working started failing to get UPS shipping quotes, which is impacting web business dramatically. After much trial and error, I found the following code that works just fine in a console application:

static string FindUPSPlease()
{
    string post_data = "<xml data string>";
    string uri = "https://onlinetools.ups.com/ups.app/xml/Rate";

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Method = "POST";
    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;

    byte[] postBytes = Encoding.ASCII.GetBytes(post_data);

    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = postBytes.Length;
    Stream requestStream = request.GetRequestStream();
    requestStream.Write(postBytes, 0, postBytes.Length);
    requestStream.Close();

    // get response and send to console
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
    Console.WriteLine(response.StatusCode);
    return "done";
}

This runs in Visual Studio just fine and gets a nice little response from UPS that the XML is, of course, malformed.

But, if I paste this function into the web application without changing a single character, an exception is thrown on request.GetRequestStream():

Authentication failed because the remote party has closed the transport stream.

I tried it in a couple of different place in the application with the same result.

What is there about the web application environment that would affect the request?

like image 344
user3091705 Avatar asked Feb 25 '18 02:02

user3091705


1 Answers

It turns out to be a TLS issue. I guess the console app uses a higher protocol by default than the web application, although none was specified. So, all you have to do is add the following line(s) of code sometime prior to making the request:

using System.Net;
...
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

That was all it took, though I spent an enormous amount of getting there.

Here is the response from UPS on the issue:

Effective January 18, 2018, UPS will only accept TLS 1.1 and TLS 1.2 security protocols... 100% of requests from customers who are on TLS 1.0 while using production URLS (onlinetools.ups.com/tool name) will be rejected.

Anyway, hope this helps someone.

Jim

like image 194
user3091705 Avatar answered Oct 07 '22 10:10

user3091705