Jamesckel
Jamesckel

Reputation: 160

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?

Upvotes: 5

Views: 2184

Answers (3)

Jamesckel
Jamesckel

Reputation: 160

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

Upvotes: 5

abc123
abc123

Reputation: 262

Try setting the default credentials or check if there is any proxy server set and pass it like in the example below.

The example is given for WebClient.

I was having problem with setting Default Credential, as proxy was enabled on the server. So i passed the proxy URL and port with credentials which can access it.

using (System.Net.WebClient web = new System.Net.WebClient())
        {
            //IWebProxy defaultWebProxy = WebRequest.DefaultWebProxy;
            //defaultWebProxy.Credentials = CredentialCache.DefaultCredentials;

            //web.Proxy = defaultWebProxy;

            var proxyURI = new Uri(string.Format("{0}:{1}", proxyURL, proxyPort));

            //Set credentials
            System.Net.ICredentials credentials = new System.Net.NetworkCredential(proxyUserId, proxyPassword);

            //Set proxy
            web.Proxy = new System.Net.WebProxy(proxyURI, true, null, credentials);

            web.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            var result = web.UploadString(URL, "");
            return result;
        }

Upvotes: 0

PSK
PSK

Reputation: 17953

Can you try setting the Credentials to your request object like following.

 request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

Upvotes: 0

Related Questions