C# HttpWebRequest times out after two server 500 errors - c#

After I make two C# HttpWebRequests that throw an exception because of "(500) Internal Server Error 500", the third attempt throws a time out exception. Why doesn't it throw another (500) Internal Server Error exception?
When I restart my application, it throws two 500 errors and then starts timing out again.
This is my code:
GetPages GetPages = new GetPages();
string test = GetPages.GetPage(); /* Exception: (500) Internal Server Error */
GetPages.Dispose();
GetPages GetPages = new GetPages();
string test = GetPages.GetPage(); /* Exception: (500) Internal Server Error */
GetPages.Dispose();
GetPages GetPages = new GetPages();
string test = GetPages.GetPage(); /* Exception: time out, why? */
GetPages.Dispose();
This is GetPages class and GetPage method:
namespace MyNamespace
{
class GetPages
{
public string GetPage()
{
this.httpRequest = (HttpWebRequest)WebRequest.Create("http://myurl");
try
{
StringBuilder postData = new StringBuilder(100);
postData.Append("test=test");
byte[] dataArray = Encoding.UTF8.GetBytes(postData.ToString());
httpRequest.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
httpRequest.KeepAlive = false;
httpRequest.Proxy = null;
httpRequest.Method = "POST";
httpRequest.Timeout = 10;
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.ContentLength = dataArray.Length;
using (this.requestStream = httpRequest.GetRequestStream())
{
requestStream.Write(dataArray, 0, dataArray.Length);
requestStream.Flush();
requestStream.Close();
this.webResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseReader = new System.IO.StreamReader(responseStream, Encoding.UTF8);
String responseString = responseReader.ReadToEnd();
MessageBox.Show(responseString);
return responseString;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return "FAIL";
}
}
public void Dispose()
{
System.GC.SuppressFinalize(this);
}
}
}
UPDATE
Thanks you all for helping out. I have not been able to solve the issue.
The dispose method is gone now.
I have made HttpWebRequest httpRequest, HttpWebResponse webResponse and Stream requestStream local and am using the following using statements:
using (webResponse = (HttpWebResponse)httpRequest.GetResponse())
{
using (Stream responseStream = webResponse.GetResponseStream())
{
using (StreamReader responseReader = new System.IO.StreamReader(responseStream, Encoding.UTF8))
{
responseString = responseReader.ReadToEnd();
}
}
}
Another update
This is the entire GetPage method now:
public string GetPage()
{
HttpWebRequest httpRequest;
HttpWebResponse webResponse;
Stream requestStream;
try
{
StringBuilder postData = new StringBuilder(100);
postData.Append("test=test");
byte[] dataArray = Encoding.UTF8.GetBytes(postData.ToString());
httpRequest = (HttpWebRequest)WebRequest.Create("http://myurl");
httpRequest.Proxy = null;
httpRequest.Method = "POST";
httpRequest.Timeout = 10;
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.ContentLength = dataArray.Length;
using (requestStream = httpRequest.GetRequestStream())
{
/* this is never reached when the time out exception starts
so the error seems to be related to too many GetRequestStreams */
requestStream.Write(dataArray, 0, dataArray.Length);
webResponse = (HttpWebResponse)httpRequest.GetResponse();
/* this is never reached when the 500 server error occurs */
String responseString = "";
using (Stream responseStream = webResponse.GetResponseStream())
{
using (StreamReader responseReader = new System.IO.StreamReader(responseStream, Encoding.UTF8))
{
responseString = responseReader.ReadToEnd();
return responseString;
}
}
}
}
catch (Exception e)
{
return "FAIL";
}
return "...";
}
** SOLVED!! **
httpRequest was not getting abort()'ed. In the catch() block I have added httpRequest.abort(), now it works correctly.

I suspect this is the problem:
this.webResponse = (HttpWebResponse)httpRequest.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream, Encoding.UTF8);
String responseString = responseReader.ReadToEnd();
You're not disposing of any of these disposable objects. That means the connection to the web server will be maintained until finalization, so the connection pool (of two connections per server) won't allow any other requests.
I suggest that:
You move the GetResponse call out of the using statement for the request stream
You remove the explicit calls to Flush and Close for the request stream (disposing of it is good enough)
You make webResponse and webRequest local variables instead of instance variables unless you really need them later, in which case you should dispose of them in your Dispose method.
You use using statements for the WebResponse, Stream, and StreamReader. (The last isn't strictly necessary, as disposing of the stream is good enough.)
You make GetPages not implement IDisposable unless you really need it to.

HTTP protocol defines that only two connection can be made at the same time to the same server. Close the responseStream after successful or unsuccessful reading.

Related

Login into iCloud via Json Post request

I'm trying to log in into iCloud using a Json Post request in C#. Before trying to implement the code I was studying a little bit the iCloud requests using Chrome Console and using an Ad-on to replicate the requests in order to obtain the same result of the website.
First of All I checked the request directly from iCloud website:
And this is the response:
{
"serviceErrors" : [ {
"code" : "-20101",
"message" : "Il tuo IDĀ Apple o la password non sono corretti."
} ]
}
Using "Advance REST Client" ad Chrome plugin to replicate the request I ve tried the same Json request to the same Url. But I get Empty response:
I Also tried to copy and paste the whole Header (All the settings) and than send the request but the response is the same:
Anyone has an Advice?
UPDATE: I tried to implement A Json request through c# program:
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://idmsa.apple.com/appleauth/auth/signin");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{accountName: \"briesanji #gmail.com\", password: \"testPassword\", rememberMe: false, trustTokens: []}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
The problem is that Execution breaks when the
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
is hit and it gives me this error: System.Net.WebException: 'Error Remote Server: (400) Request not valid.'
UPDATE: I solved in this way:
void POST(string url, string jsonContent)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(jsonContent);
request.ContentLength = byteArray.Length;
request.ContentType = #"application/json";
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
long length = 0;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
length = response.ContentLength;
}
}
catch (WebException ex)
{
// Log exception and throw as for GET example above
}
}
string GET(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
catch (WebException ex)
{
WebResponse errorResponse = ex.Response;
using (Stream responseStream = errorResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// log errorText
}
throw;
}
}
Anyways I tested also the Answer and it was good to.. So I check it as valid thanks.
With this i dont get any error and the response content of the second request just tells me that there were too many failed logins for the test account...
private static void ICloud()
{
var cc = new CookieContainer();
var first = (HttpWebRequest)WebRequest.Create("https://idmsa.apple.com/appleauth/auth/signin?widgetKey=83545bf919730e51dbfba24e7e8a78d2&locale=de_DE&font=sf");
first.Method = "GET";
first.CookieContainer = cc;
var response1 = (HttpWebResponse)first.GetResponse();
using (var streamReader = new StreamReader(response1.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
var second = (HttpWebRequest)WebRequest.Create("https://idmsa.apple.com/appleauth/auth/signin");
second.ContentType = "application/json";
second.Method = "POST";
second.Accept = "application/json";
second.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
second.Referrer = "https://idmsa.apple.com/appleauth/auth/signin?widgetKey=83545bf919730e51dbfba24e7e8a78d2&locale=de_DE&font=sf";
second.Headers.Add("X-Requested-With", "XMLHttpRequest");
second.Headers.Add("X-Apple-Widget-Key", "83545bf919730e51dbfba24e7e8a78d2");
using (var streamWriter = new StreamWriter(second.GetRequestStream()))
{
string json = "{\"accountName\":\"test#icloud.com\",\"password\":\"test\",\"rememberMe\":false,\"trustTokens\":[]}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
try
{
var response2 = (HttpWebResponse)second.GetResponse();
using (var streamReader = new StreamReader(response2.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
catch(WebException we)
{
using (var r = new StreamReader(we.Response.GetResponseStream()))
{
var result2 = r.ReadToEnd();
}
}
}

Getting content from httpwebresponse exception

My remote server is throwing a web exception as bad request. But I know there is more information included in the error than what I get. If I look at the details from the exception it does not list the actual content of the response. I can see the content-type, content-length and content-encoding only. If I run this same message through another library (such as restsharp) I will see detailed exception information from the remote server. How can I get more details from the response since I know the remote server is sending them?
static string getXMLString(string xmlContent, string url)
{
//string Url;
string sResult;
//Url = ConfigurationManager.AppSettings["UserURl"] + url;
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/xml";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(xmlContent);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
sResult = result;
}
}
return sResult;
}
EDIT : Have you tried with a simple try-catch to see if you can get more details ?
try
{
var response = (HttpWebResponse)(request.GetResponse());
}
catch(Exception ex)
{
var response = (HttpWebResponse)ex.Response;
}
In my recherches in an answer for you, I noticed that in code there was something about encoding, that you didn't specified. Look here for exemple with such code.
var encoding = ASCIIEncoding.ASCII;
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
string responseText = reader.ReadToEnd();
}
Or here, in the doc, also.
// Creates an HttpWebRequest with the specified URL.
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
// Sends the HttpWebRequest and waits for the response.
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
// Gets the stream associated with the response.
Stream receiveStream = myHttpWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader( receiveStream, encode );
Console.WriteLine("\r\nResponse stream received.");
Have you tried with such ?

Call Genderize.io API From C#

I'm trying to call http://genderize.io/ , but i'm getting an error from .NET saying:
{"You must provide a request body if you set ContentLength>0 or SendChunked==true. Do this by calling [Begin]GetRequestStream before [Begin]GetResponse."}
How would I call this web service "http://api.genderize.io/?name=peter" from C# and get a JSON string back?
HttpWebRequest request;
string postData = "name=peter"
URL = "http://api.genderize.io/?"
Uri uri = new Uri(URL + postData);
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
request.AllowAutoRedirect = true;
UTF8Encoding enc = new UTF8Encoding();
string result = string.Empty;
HttpWebResponse Response;
try
{
using (Response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = Response.GetResponseStream())
{
using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
{
return readStream.ReadToEnd();
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Error: " + ex.Message);
throw ex;
}
You are making the call to the service using POST method, reading through the comments area in http://genderize.io/ the author states that only GET method requests are allowed.
Stroemgren: Yes, this is confirmed. Only HTTP GET request are allowed.
This answer probably would be better as a comment, but I don't have enough reputation :(

A first chance exception of type "System.ArgumentException" occured in mscorlib.dll

try
{
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)",
res.StatusDescription);
read1.Close();
rs.Close();
}
catch (Exception e1)
{
Console.WriteLine(e1.Message);
}
I am trying to access ftp server via C#.
However, the code errors with an exception:
A first chance exception of type "System.ArgumentException" occured in mscorlib.dll. Stream was not readable.
Any help will be appreciated.
Put all IDisposable resources within using(...) {...}. That technics prevents
resource leaking/closed resources invoking:
try {
FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
// Response: we're going to work wuth respose within "using" block only
using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
Console.WriteLine(resp.WelcomeMessage);
// Reader: once again reader's opened once and called within using only
using (StreamReader reader = new StreamReader(resp.GetResponseStream())) {
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("Directory is complete, status(0)", resp.StatusDescription);
}
}
catch (Exception ex) { // <- Bad idea to catch all possible exceptions without "throw;"
Console.WriteLine(ex.Message);
}
TLDR; The state of the FtpWebResponse object is disposed, therefore you cannot read the response stream. The stream is closed.
Disassembly of FtpWebResponse:
public override void Close()
{
if (Logging.On)
{
Logging.Enter(Logging.Web, this, "Close", "");
}
if (this.HttpProxyMode)
{
this.m_HttpWebResponse.Close();
}
else
{
Stream responseStream = this.m_ResponseStream;
if (responseStream != null)
{
responseStream.Close();
}
}
if (Logging.On)
{
Logging.Exit(Logging.Web, this, "Close", "");
}
}
The reason you get the exception, is that you are reading the response:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
}
and on the next line, you try to read the response again, into another variable: res
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
In that section, you also do a call to the res.GetResponseStream() twice, but that does not matter in terms of the error occuring. The error will occur even if you change it to:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
Or:
FtpWebResponse res = (FtpWebResponse)req.GetResponse();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
The reason that the error occurs, is the state of the FtpWebResponse object, which is disposed; and has the StatusCode = ClosingData. When I try to read the stream in that state, I get the error you are experiencing. In the using block before, the StatusCode = OpeningData.
However, if you just change a couple of lines to:
using (var resp = (FtpWebResponse)req.GetResponse())
{
Console.WriteLine(resp.WelcomeMessage);
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A
Console.WriteLine(read1.ReadToEnd());
Console.WriteLine("Directory is compleate,status(0)", res.StatusDescription);
}
When entering this using scope, the StatusCode = OpeningData, and stream is available and readable. When exiting the scope, the StatusCode = ClosingData, and stream will not be readable.
Hope this make some sense, and correct me if I'm wrong. :-)
With these small changes your code will run as expected. However you should look into the pattern #DmitryBychenko proposes. That way you will have access to the resources within the scope that they're needed, and disposed afterwards.

Code analysis complains that object can be disposed more than once. Why?

I get warning on responseStream in following function:
private static string GetResponseString(WebResponse response)
{
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (var responseReader = new StreamReader(responseStream))
{
var strResponse = responseReader.ReadToEnd();
return strResponse;
}
}
}
return string.Empty;
}
I call this function from places like like this one:
var request = (HttpWebRequest)WebRequest.Create(Uri);
request.Headers.Add("Authorization", "GoogleLogin auth=" + this.SecurityToken);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Timeout = 5000;
// build the post string
var postString = new StringBuilder();
postString.AppendFormat("registration_id={0}", recipientId);
postString.AppendFormat("&data.payload={0}", message);
postString.AppendFormat("&collapse_key={0}", collapseKey);
// write the post-string as a byte array
var requestData = Encoding.ASCII.GetBytes(postString.ToString());
request.ContentLength = requestData.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(requestData, 0, requestData.Length);
requestStream.Close();
// Do the actual request and read the response stream
try
{
var response = request.GetResponse();
var responseString = GetResponseString(response);
response.Close();
return responseString.Contains("id=")
? SendStatus.Ok
: GetSendStatusFromResponse(responseString);
}
catch (WebException ex)
{
var webResponse = (HttpWebResponse)ex.Response;
if (webResponse != null)
{
if (webResponse.StatusCode.Equals(HttpStatusCode.Unauthorized))
{
return SendStatus.Unauthorized;
}
if (webResponse.StatusCode.Equals(HttpStatusCode.ServiceUnavailable))
{
return SendStatus.ServiceUnavailable;
}
}
this.LoggerService.Log(null, ex);
return SendStatus.GeneralException;
}
StreamReader takes ownership of the stream passed to it in the constructor call in the sense that it will call Dispose on it when the StreamReader itself is closed - hence it will already be disposed when the outer Using statement attempts to dispose of it.

Categories