I have a very simple service which calls to a URL and captures a status that is written out by that service;
// Service call used to determine availability
System.Net.WebClient client = new System.Net.WebClient();
// I need this one (sorry, cannot disclose the actual URL)
Console.WriteLine(client.DownloadString(myServiceURL + ";ping"));
// I added this for test purposes
Console.WriteLine(client.DownloadString("https://www.google.com"));
The "DownloadString" for myServiceURL line throws the error "The underlying connection was closed: An unexpected error occurred" and there's nothing showing in Fiddler for this line, whereas the "DownloadString" for google.com works and I see the console output for that.
Following other suggestions for the error, I have tried combinations of setting UseDefaultCredentials, Encoding options, adding appropriate headers to the request, none of which make any difference.
client.UseDefaultCredentials = true;
client.Encoding = Encoding.UTF8;
When I navigate to the myServiceURL in a browser, it works and shows "OK", as expected.
Another method from the same service has been coded as follows:
// Request
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(myServiceURL + ";login");
// Set the request configuration options
req.Method = "POST";
req.ContentType = "text/xml";
req.ContentLength = bytes.Length;
req.Timeout = -1;
// Call for the request stream
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
// ....snip
// This line fails with the same error as before
WebResponse resp = req.GetResponse()
This is all being run on a Windows 7 (64-bit) PC using .NET Framework 4.0; the service at myServiceURL is a 3rd-party service for which I have no control over.
Have finally got to the bottom of this and whilst the answer may not apply to everyone with the same problem; I would suggest that the clue was in the fact that we could pull information from some HTTPS site, but not all and tracing events through a combination of Fiddler, WireShark and our Firewall.
Opening the sites in Google Chrome and clicking the padlock for 'https' in the URL address for the site, to view the 'Security Overview' we see that for most of the sites we tried that there are entries listed for 'Valid Certificate' and for 'Secure Resources', but this one site also had an entry for 'Secure TLS Connection' and WireShark confirmed that the handshake (from Chrome) was using TLS v1.2
TLS v1.2 appears to only be supported with .NET Framework 4.5 (or above), which therefore needs Visual Studio 2012 (or above)
We are currently running .NET Framework 4.0 with Visual Studio 2010
Downloaded Visual Studio 2015 Community Edition to test the "same" code within a project using .NET Framework 4.5.2 and it worked straight away.
//assuming this is set
byte[] Data;
string url = string.Format("{0};{1}" ,myServiceURL, "login");
// Request
HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(url);
wreq.Method = "POST";
wreq.Proxy = WebProxy.GetDefaultProxy();
(wreq as HttpWebRequest).Accept = "text/xml";
if (Data != null && Data.Length > 0)
{
wreq.ContentType = "application/x-www-form-urlencoded";
System.IO.Stream request = wreq.GetRequestStream();
request.Write(Data, 0, Data.Length);
request.Close();
}
WebResponse wrsp = wreq.GetResponse();
Related
Scenario
Win10 x64
VS2013
I'm trying to make a WebRequest, but I'm getting the following error:
The underlying connection was closed: An unexpected error occurred on a send.
Digging into the inner exception, I got:
"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."
The code which does the request is the following:
private static Hashtable exec (String method, String uri, Object data, String contentType) {
Hashtable response;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create (API_BASE_URL + uri);
request.UserAgent = "MercadoPago .NET SDK v"+MP.version; //version resolves to 0.3.4
request.Accept = MIME_JSON; // application/json
request.Method = method; //GET
request.ContentType = contentType; //application/json
setData (request, data, contentType); //setData in this case does nothing.
String responseBody = null;
try {
HttpWebResponse apiResult = (HttpWebResponse)request.GetResponse (); //Error throws here
responseBody = new StreamReader (apiResult.GetResponseStream ()).ReadToEnd ();
response = new Hashtable();
response["status"] = (int) apiResult.StatusCode;
response["response"] = JSON.JsonDecode(responseBody);
} catch (WebException e) {
Console.WriteLine (e.Message);
}
}
What i've already done:
Made the request via Console Application and MVC Application controller. Both throws the same exception
Called the API via Postman with the exact same headers, which brings me the content correctly.
Those requests were working okay via c# about 4 days ago and I suddenly started having issues, but considering the fact that it responds okay for Postman, I can't figure out where's the problem.
Here's Postman's response
EDIT: Did both requests with Fiddler listening. The result for Postman shows a direct request to the API with HTTPS. When trying with my ConsoleApplication, it shows a HTTP request, which makes a tunnel to the API endpoint, port 443.
The TextView from Fiddler for the tunnel request says the following:
I noticed the "time" field which refers to a very old date, but i don't know what does it mean.
It is kind of bad practice to enable Tls12 like this-
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
In future, if you'd need to use higher version of TLS, you'll have to update your code.
If you are using an older version of .NET, you can simply switch it higher version in which Tls12 is enabled by default.
For example, this simple change in your web.config will enable Tls12 automatically-
<httpRuntime targetFramework="4.6.1"/>
You can try the code below:
string url = ""; // url of the endpoint
WebClient client = new WebClient();
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
client.Encoding = Encoding.UTF8;
client.Headers.Add("content-type", "application/json"); // same as other parameters in the header
var data = client.DownloadString(url);
Figured it out. I needed to include the use of TLS1.2.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
(As a reference for others who have the same issue)this also might be the result of a Double Hop issue , where you should pass the credited user along(in the pool) to the passing server or from one Environment to the other , otherwise the user is set to "ANONYMOUS/USER" and you will get a "An existing connection was forcibly closed by the remote host." Error
i found same error, just mention
request.UserAgent = "anything u want";
I am trying to connect to an API, via C# and WinForms, to download some data from a server. I am using the latest version of visual studio (2017 at the time of writing).
The API I am using: https://www.whosoff.com/features/api/
As per the API setup, I have already got an authentication key and my IP has been white listed.
What I have so far:
try{
var request =(HttpWebRequest)WebRequest.Create("https://wr1.whosoff.com/api/whosoff?start_date=01-Apr-2018&end_date=25-Apr-2018");
request.Method = "GET";
request.Headers.Add("AUTH-KEY", "MY_AUTH_KEY");
var response = (HttpWebResponse)request.GetResponse();
string content = string.Empty;
using (var stream = response.GetResponseStream())
{
using (var sr = new StreamReader(stream))
{
content = sr.ReadToEnd();
}
}
}
} catch(Exception ex){
MessageBox.Show(ex.Message.ToString());
}
This does not work - it throws an exception; "The underlying connection was closed: An unexpected error occurred on a send."
I can connect to other sites API's using this format - can anyone point me in the right direction?
UPDATE
So it turns out the issue was with TLS certificates and the fact that the API services requires TLS 1.2, which by default is turned off. It can be enabled by inserting the following code into your project
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
After inserting this code, everything worked as expected.
ORIGINAL POST
For anyone that is interested; the code above DID in fact work. It turns out that debug mode within Visual Studio causes this weird behavior - how and why I am not sure.
But when running the EXE file directly from the debug folder; it worked fine.
Weird. Anyway I ended up changing to Newtonsoft.JSON and using the following code;
var client = new RestSharp.RestClient("API URL");
/* Create a new request to send to the client */
var request = new RestSharp.RestRequest(RestSharp.Method.GET);
/* Add the correct headers for authentication and format */
request.AddHeader("AUTH-KEY", "MY KEY");
request.AddHeader("Content-Type", "application/json; charset=utf-8");
/* Get the response */
var response = client.Execute(request);
var content = response.Content;
I have built wcf. it is working well
The issue is when I call it many times it displays the following error:
The server encountered an error processing the request. See server
logs for more details
I configured a WCF Tracing File but it remains always empty. what can be the reason of this sudden stop of the service and how to fix it?
Here is the code that I use at the client's side every 20 seconds:
string url = "http://host/Service.svc/method";
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);
webrequest.Method = "GET";
ASCIIEncoding encoding = new ASCIIEncoding();
HttpWebResponse webresponse = (HttpWebResponse)webrequest.GetResponse();
Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
StreamReader loResponseStream =
new StreamReader(webresponse.GetResponseStream(), enc);
string strResult = loResponseStream.ReadToEnd();
loResponseStream.Close();
webresponse.Close();
I fixed the issue. it was due to open database connections. I missed to close, at the server side, the database connections. Thank you for answer
It could be a working memory issue on the server/host. If there's less than 5% available you get no response.
I am new to .net and APIs and am currently using .Net 4.5 to connect to an API using rest. The problem I am having is I get an exception thrown back in the return xml that says "Cannot forward request to server with name", "Cannot read data from connection", Connection reset", full error below.
What is odd is this script works fine on smaller datasets but when the response is large enough, I get that exception from the server thrown back. What has helped setting the keep alive to true, using httpversion10, and specifying gzip and sendchunked. I am using advanced rest client to test the server in chrome addins and it returns data fine on there with these larger dataset. It will not with the script below. I am suspecting there is a difference in the way I am telling the server to handle my response verses the chrome add in. Any suggestions on how I improve the performance of this?
This is what the advanced rest client settings look like that work for the Chrome add in.
This is the code I have which appears to need changes to make it handle the request/response better.
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(#"magicalwebsite");
req.KeepAlive = true;
req.ProtocolVersion = HttpVersion.Version10;
req.ServicePoint.ConnectionLimit = 24;
req.Timeout = 2000000000;
req.Method = "Post";
req.Accept = "*/*";
req.SendChunked = true;
req.AutomaticDecompression = DecompressionMethods.GZip;
//Xml request file for data
string postData = System.IO.File.ReadAllText(#"C:\Users\yo\Desktop\testtest.txt");
//sending header and content
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
req.ContentType = "text/xml";
req.ContentLength = byteArray.Length;
req.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes("xxxx:xxxxx"));
Stream dataStream = req.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
//Requesting response of data
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
//Grabbing response
using (Stream stream = resp.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
String responseString = reader.ReadToEnd();
}
This is the exception I am getting in the xml being thrown back.
<?xml version="1.0" encoding="UTF-8"?>
<response success="false">
<messages>
<message key="exception-caught">Caught Exception: Caught Exception:
Cannot forward request to server with name=prod-euapp01
com.magicalpony.exception.APException: Cannot forward request to server with name=prod-euapp01
at com.magicalpony.webservices.APIForwarder.forward(APIForwarder.java:105)
at com.magicalpony.webservices.APIServlet.forwardRequest(APIServlet.java:270)
at com.magicalpony.webservices.APIServlet.wrongServer(APIServlet.java:253)
at com.magicalpony.webservices.APIServlet.service(APIServlet.java:124)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter
(ApplicationFilterChain.java:210)
at com.magicalpony.system.WebServiceMonitor.doFilter(WebServiceMonitor.java:61)
at org.apache.catalina.core.
ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.magicalpony.system.HitTracer.doFilter(HitTracer.java:133)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:303)
at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:183)
at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:169)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.magicalpony.exception.APException:
Cannot read data from connection
at com.magicalpony.webservices.NetUtil.readData(NetUtil.java:61)
at com.magicalpony.webservices.APIForwarder.forward(APIForwarder.java:102)
... 26 more
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at
java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:687)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1323)
at com.magicalpony.webservices.NetUtil.readData(NetUtil.java:58)
... 27 more</message>
</messages>
</response>
The problem is with DNS resolution.
Step 1: Enter your domain name in a browser and see if Server is available.
Step 2: If server is available with domain name then you got to fix the IP Address or DNS resolution.
You can fix this by updating the IP Address in your PC (Follow steps below)
Go to a folder: C:\Windows\System32\drivers\etc
Copy and paste "hosts" file to desktop.
Update your host file with your IP Address and domain name.
Step 3: Copy and Paste hosts file in original folder (C:\Windows\System32\drivers\etc).
Step 4: Test your API.
Using values against chrome's Advanced REST Client works fine when I feed in the same values and settings as used in my dot net 4.0 app.
On the other hand, when I attempt to consume a clients REST service from dotnet, my app immediately falls over when I call webRequest.GetRequestStream() with exception {"The underlying connection was closed: An unexpected error occurred on a send."}, HREsult -2146233079, inner exception ""Authentication failed because the remote party has closed the transport stream." HResult -2146232800
Here's my code, but I've changed some values to protect my client's details.
When the code attempts to getrequeststream(), my fiddler monitor raises 2 entries to show my app is contacting the server. Shouldn't it just be creating a whole packet with authorization headers and the json content and sending it in a single call? or is this how POST usually works? Fiddler never picks up activity from chrome's ARC so I can't compare.
I've tried WebRequest, webclient, httpwebrequest etc and can't get any of them working. (I can't use the new webclient class as my main app is dotnet 4.0). I run VS in administrator mode. How can chrome's Advanced REST client work, but mine not? What's the difference?
string parsed = #" {
"data": {
"workoutDate": "2015-01-23",
"exerciseType": "TREADMILL",
"workoutDuration": 1456,
"distance": 1382.0,
"energyConsumed": 567068.0,
"averageHeartRate": 75.0,
"averageSpeed": 1.0
},
"user": {
"email": "bumbly.boms#pdd.com",
"firstName": "Len",
"lastName": "BlTestoomers",
"gender": "MALE",
"dateOfBirth": "1984-10-27"
}
}";
// Add authorization headers
string authentication = string.Format("Authorization: RRgym SNUFFCENTRE:{0}:gymId246", EyupSecurityKey.GenerateAuthenticationKey());
// Convert the parsed string into byte[]
byte[] buffer = Encoding.UTF8.GetBytes(parsed);
string addr = "https://equipment.test.pogram.uk/acr-rest/equipment/v1/workout/endurance";
WebRequest webRequest = WebRequest.Create(addr);
webRequest.Method = WebRequestMethods.Http.Post;
webRequest.ContentType = "application/json";
webRequest.ContentLength = buffer.Length;
webRequest.Headers.Add(authentication);
Stream newStream = webRequest.GetRequestStream();
// Send the data.
newStream.Write(buffer, 0, buffer.Length);
newStream.Close();
}
I'll post this to help others that might have the same problem.
I've been contacted by the client to say that my problem may be because their server is set to a higher security level than base visual studio. (Chrome ARC must be handling it ok).
So I had to set
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
just before creating my webrequest.
Unfortunately that's a protocol that's not supported in dotnet4.0 but is in 4.5 so I need to come up with a fix. But that's another day :)