https request fails only in .net web app - c#

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?

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

Can you try setting the Credentials to your request object like following.
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

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;
}

Related

"The request was aborted: Could not create SSL/TLS secure channel" in HttpWebRequest, even after specifying ServicePointManager.SecurityProtocol

In order to meet PCI compliance, we have had to completely disable TLS 1.0 from our servers. Ever since doing this, I have had to specify which protocol to use when making web requests in order for things to work. However, one particular problem persists. Even when I specify the protocol, I still get the error stated in the title.
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.KeepAlive = false;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(body);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
The error itself is generated from the line -
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
As you can see, I am specifying to use either TLS 1.1 or 1.2 (I originally had it at 1.2 only, but thought allowing 1.1 as well would help, but it did not).
Additionally (not sure if this is pertinent or not), this particular snippet of code is always calling an API that we also run and maintain, so essentially, the server is calling itself to get a piece of info it needs.
And I am fast running out of ideas on what I can try to further debug or fix this, so any help out there would be greatly appreciated.
I finally figured this one out, and the solution is far simpler than I'd like to admit. I simply moved the line
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
to the very top of the code snippet I posted in the question, and everything has been working since. I'm guessing it needs to be in place before creating the HttpWebRequest?

wowza streaming c# HTTP get method for livestreamrecord

Hello I need some help with livestreamrecord recording via http url c# calls,
I can start and stop a stream recording using:
http://[username]:[password]#[wowza-ip-address]:8086/livestreamrecord?app=live&streamname=myStream&action=startRecording
When inputting it directly in to a browser or when I redirect my webpage to it from code, but when I try to do the same from c# on a webpage nothing happens.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://[username]:[password]#[wowza-ip-address]:8086/livestreamrecord?app=live&streamname=myStream&action=startRecording);
request.Method = "GET";
request.Proxy = new WebProxy("[wowza-ip-address]", 8086);
request.Credentials = new NetworkCredential("[username]", "[password]");
request.ContentType = "application/x-www-form-urlencoded";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stm = response.GetResponseStream();
When I first tried to set it up I kept getting 401 unauthorized error which the code above no long throws, but now I'm stuck as no error is thrown and still no recording is started.
The response returns:
<html><head><title>Wowza Streaming Engine 4 Perpetual Edition 4.0.1 build10615</title></head><body>Wowza Streaming Engine 4 Perpetual Edition 4.0.1 build10615</body></html>
Which indicates it is not reaching the livestreamrecord page.
Ben
Sovled the problem, thier was a 302 redirect on the request which was producing the 401 unauthorized responses. Adding:
request.AllowAutoRedirect = false;
and removing:
request.Proxy = new WebProxy("[wowza-ip-address]", 8086);
Resolved the problem.
With Proxy in, it didn't throw an error but also didn't record. Removing Proxy allowed the record command to work but throw the 401 response which was then resolved by setting AllowAutoRedirect to false.

The remote server returned an error: (407) Proxy Authentication Required

I referred several websites, which had answer for this question
"The remote server returned an error: (407) Proxy Authentication Required." ,but none were helpful.
I wrote a sample code to check the proxy authentication in office. The code throws exception.
My requirement:- Verify what the website returns. Outside office, the code works fine, but in office it throws an exception due to proxy.
When I hardcode the credentials using new NetworkCredential, it works fine.
int ResponseCode;
string url = "http://www.msftncsi.com/ncsi.txt";
WebRequest request = WebRequest.Create(url);
request.Credentials = CredentialCache.DefaultCredentials;
using (WebResponse response = request.GetResponse())
{
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
ResponseCode = (int)((HttpWebResponse)response).StatusCode;
reader.Close();
}
I do not want to Hardcode. I referred the solution in http://social.msdn.microsoft.com/Forums/is/csharpgeneral/thread/c06d3032-dceb-4a1a-bb6a-778fd13a938a, but even that didnt help.
What am I missing?
I had the same issue, this did the trick for me
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
There are many things here. You can try setting Credentials explicitly
request.Credentials = new NetworkCredentials(username, password)
You might need to specify proxy. By default it uses your IE proxy. You might not want that
WebRequest webRequest = WebRequest.Create("http://stackoverflow.com/");
webRequest.Proxy = new WebProxy("http://proxyserver:80/",true);

Logging in to eBay using HttpWebRequest fails due to 'The browser you are using is rejecting cookies' response

I'm trying to log in to my eBay account using the following code:
string signInURL = "https://signin.ebay.com/ws/eBayISAPI.dll?co_partnerid=2&siteid=0&UsingSSL=1";
string postData = String.Format("MfcISAPICommand=SignInWelcome&userid={0}&pass={1}", "username", "password");
string contentType = "application/x-www-form-urlencoded";
string method = "POST";
string userAgent = "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)";
CookieContainer cookieContainer = new CookieContainer();
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(signInURL);
req.CookieContainer = cookieContainer;
req.Method = method;
req.ContentType = contentType;
req.UserAgent = userAgent;
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] loginDataBytes = encoding.GetBytes(postData);
req.ContentLength = loginDataBytes.Length;
Stream stream = req.GetRequestStream();
stream.Write(loginDataBytes, 0, loginDataBytes.Length);
stream.Close();
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
StreamReader xsr = new StreamReader(res.GetResponseStream());
String responseText = xsr.ReadToEnd();
Obviously substituting my real username and password. When I look at the string responseText, I see that part of the response from eBay is
The browser you are using is rejecting cookies.
Any ideas what I'm doing wrong?
P.S. And yes, I am also using the eBay API, but this is for something slightly different than what I want to do with the API.
You're doing a direct http request. The Ebay site has functionality to talk to a browser (probably to store the session cookie). Unless you make the request code smart enough to use cookies correctly it won't work. You'll probably have to use the internet explorer object instead.
Before doing the POST you need to download the page with the form that you are submitting in your code, take the cookie they give you, put it in your CookieContainer (making sure you get the path right) and post it back up in your request.
To clarify, while you might be POSTing the correct data, you are not sending the cookie that needs to go with it. You will get this cookie from the login page.
You need to intercept the http traffic to see what exactly what had happened. I use Fiddler2. It is the good tools for debugging http. So I can know whos wrong, my application or the remote web server.
Using fiddler, you can see the request header, response header with its cookies as well as response content. It used in the middle of your app and the Ebay.
Based on my experience. I think it is because Ebay cookie sent to you is not send back to Ebay server. Fiddler will prove it whether yes or not.
Another thing, the response cookie you receive should be send back to next request by using the same CookieContainer.
You should notice that CookieContainer has a bug on .Add(Cookie) and .GetCookies(uri) method. You may not using it, but internal codes might use it.
See the details and fix here:
http://dot-net-expertise.blogspot.com/2009/10/cookiecontainer-domain-handling-bug-fix.html
CallMeLaNN

Difficulty with BugzScout.net from behind a proxy

I'm attempting to use Fogbugz's BugzScout in order to automatically submit unhanded application exceptions to my Fogbugz on demand Account. I've written up a wrapper class for it and everything appears to be just groovy - on my box. Testing the same code in the production environment, behind a Proxy that requires authentication, I have had nothing but issues.
I went to work modifying the BugzScout code in order to get it to authenticate with the Proxy, and after trying many different methods suggested via a Google search, found one that works! But now I'm getting an "Connection actively refused" error from Fogbugz itself, and I don't know what to do.
Here is the code where the BugzScout connects via a .net WebClient to submit a new case, with my modifications to deal with our Proxy. What am I doing that would cause Fogbugz to refuse my request? I've removed all non web-client related code from the procedure for ease of reading.
public string Submit(){
WebClient client = new WebClient();
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Byte[] response = client.DownloadData(fogBugzUrl);
string responseText = System.Text.Encoding.UTF8.GetString(response);
return (responseText == "") ? this.defaultMsg : responseText;
}
The url is correct and the case is filled in properly- this has been verified.
EDIT: Additional info.
Using Fogbugz on Demand.
Using FogBugz.net code in it's entirety, with only these additions
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Error occurs when attempting to connect to both https://oursite.fogbugz.com/scoutsubmit.asp and http://oursite.fogbugz.com//scoutsubmit.asp (except one says port 443, and the other port 80, obviously)
I don't know anything about web authentication so I can't tell you what kind I'm using- if you tell me where to look I'd be happy to answer that for you.
Got the fix from Fogbugz- this is the appropriate network code to get though the proxy authentication and not mis-authenticate with Bugzscout.
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
WebRequest request = WebRequest.Create(fogBugzUrl);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
Is your fogbugzUrl using HTTP Basic Authentication? Is it SSL (hosted on On Demand?)
The connection actively refused message would be coming from the web server itself, not really FogBugz.
Can you post the HTTP Status Code?
One thing to note if you are using FogBugz On Demand is you HAVE to use the https:// url (not the http url).

Categories