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;
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’m trying to debug a problem.
I have been given a url to which I can send JSON commands via HTTP POST. If I stick the URL into Chrome I get a properly formatted response – all good.
If I put the same url into internet explorer (IE 11) I get a ‘The website is unable to display the webpage -This error (HTTP 501 Not Implemented or HTTP 505 Version Not Supported) means that the website you are visiting doesn’t currently have the ability to display the webpage, or support the HTTP version used to request the page.’ – Not sure whats going here
I ultimately need to send a command via a web service, to this end I have created a very simple app in visual studio.
I use this code, but then I get the error:
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://URL.....");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new
{
operation = "****",
username = "****",
password = "****"
});
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
{"No connection could be made because the target machine actively refused it 1.1.1.1:443"}
There is a problem, but being new to this I have no idea where to start looking.
Any pointers appreciated.
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();
I am working on a project that uses proxy to obtain websites' HTML code.
Now, the trouble I have is that I want to use Username-Password authentication and not IP-Auth when connecting to the proxy.
I have written a sample code and ran it with Snippy. It worked. Then I copied the same code into a Visual Studio .NET 4.5 Project and it failed with the error: An existing connection was forcibly closed by the remote host when trying to get the response.
Here is the code:
WebProxy[] proxies = { new WebProxy("ip", port) };
proxies[0].Credentials = new NetworkCredential { UserName = "username", Password = "password" };
string url = "https://www.google.com/search?q=s&num=50";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Proxy = proxies[0];
using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
{
using (StreamReader response_stream = new StreamReader(res.GetResponseStream())
{
string html = response_stream.ReadToEnd();
Console.WriteLine(html);
}
}
I have tried different variations. When I switch to authorization by IP, add mine and comment out the NetworkCredentials assignment, the code works perfectly both in Snippy and Visual Studio.
But why does it fail when using NetworkCredentials?
OK, I found the culprit. It was my proxy provider.
Note for everybody ever running into problems when testing proxy connection with HttpWebRequest -- try another seller. It might save you a couple of minutes. Or hours.
I have been using this code to read in a file from a document repository in sharepoint:
WebResponse objResponse;
WebRequest objRequest = System.Net.HttpWebRequest.Create("http://servername/realestate/SiteAssets/navigation.txt");
objRequest.Timeout = 10000;
objRequest.UseDefaultCredentials = true;
objRequest.Proxy.Credentials = objRequest.Credentials;
objResponse = (WebResponse)objRequest.GetResponse();
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
navBar = sr.ReadToEnd();
sr.Close();
}
I just migrated to a new environment, and I am getting a 401 unauthorized error with this code - but, instead of using servername, I am now using hostname (since the new environment has a domain assigned to it). How can I navigate this issue, even though I am now using a host in my HttpWebRequest object? And, if this should not be causing the issue, I would like to hear recommendations as well. Thanks.
Local Loopback check?
KB 896861 - You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or a later version