c# httpwebrequest getResponse() freezes and hangs my program - c#

I was trying to use httpwebrequest to use a rest like service on a remote server and from the first execution itself, my code was hanging the program. Then I tried it as a console application to make sure it has nothing to do with the program itself but no luck!
string credentialsJson = #"{""username"":""test"",
""password"":""test""
}";
int tmp = ServicePointManager.DefaultConnectionLimit;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"https://qrua.com/qr/service" + #"/auth/login");
request.Method = "POST";
request.KeepAlive = true;
request.Timeout = 50000 ;
request.CookieContainer = new CookieContainer();
request.ContentType = "application/json";
try
{
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(credentialsJson);
}
catch (Exception e)
{
Console.WriteLine("EXCEPTION:" + e.Message);
}
//WebResponse response = request.GetResponse();
try
{
using (WebResponse response = (HttpWebResponse)request.GetResponse())
{
Console.WriteLine("request:\n" + request.ToString() + "\nresponse:\n" + response.ContentLength);
response.Close();
}
}
catch (Exception e)
{
Console.WriteLine("EXCEPTION: in sending http request:" + " \nError message:" + e.Message);
}
Tried several things from different forums but it doesnt help. Even a simple console app with the above code hangs the console indefinitely! Any help would be great..
Thanks

You're never closing the StreamWriter... so I suspect it's not being flushed. Admittedly I'd expect an error from the server instead of just a hang, but it's worth looking at.
Btw, you don't need to close the response and dispose it. Just the using statement is enough.

There's not much you can do if the remote server is not responding other than defining a Timeout and catch the exception as you did in order to inform the user that the operation cannot complete because the remote site didn't respond:
var request = (HttpWebRequest)WebRequest.Create("https://qrua.com/qr/service/auth/login");
request.Timeout = 5000;
// If the server doesn't respond within 5 seconds you might catch the timeout exception
using (var response = request.GetResponse())
{
}
If you don't want to freeze the UI you could use the async version: BeginGetResponse

Try specifying request.ContentLength.
Before doing:
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(credentialsJson);
Try something like this:
using (MemoryStream stream = new MemoryStream())
{
using (var writer = StreamWriter writer = new StreamWriter(stream))
{
writer.Write(credentialsJson);
writer.Close();
}
request.ContentLength = stream.Length;
}

Related

C# API GetResponse issue

I'm quite new to c# and I'm having an issue when trying to call an API to post some CSV data using the following code:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myurl");
request.Method = "POST";
request.Headers.Add("X-Api-Key:" + apiKey);
request.Headers.Add("X-Api-Secret:" + apiSecret);
request.ContentType = "text/csv";
using (StreamWriter swCSVData = new StreamWriter(request.GetRequestStream()))
{
StreamReader csvReader = new StreamReader(File.OpenRead("C:\\Test\\conf-ato-sprmbrinfo-batch-001.csv"));
while (!csvReader.EndOfStream)
{
swCSVData.WriteLine(csvReader.ReadLine());
}
csvReader.Close();
}
HttpWebResponse response = null;
try
{
Console.WriteLine("Attempting response....");
response = (HttpWebResponse)request.GetResponse();
Console.WriteLine("Got response....");
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (StreamReader reader = new StreamReader(responseStream))
{
strResponseValue = reader.ReadToEnd();
}
}
}
Console.WriteLine(strResponseValue);
File.WriteAllText("C:\\Test\\apioutput.txt",strResponseValue);
}
catch ( Exception ex)
{
strResponseValue = "{\"errorMessages\":[\"" + ex.Message.ToString() + "\"],\"errors\":{}}";
}
If I run this code using the post test at ptsv2.com, then I can see that the api call looks like I would expect and I get a response. However, when I change my code to point to my required URL it seems to just hang on the following line:
response = (HttpWebResponse)request.GetResponse();
Does anyone have any idea as to why this could be happening?
Also happy for any recommendations to make my code better.
Thanks in advance.
It turns out this was a security issue once I could see the exception being returned. I had to add the following line of code for my request:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Thanks to the people who took the time to comment on my original question.

Threaded HttpWebResponse doesn't always fire

This code is being run within a web service. Sometimes it executes fine and sometimes it seems like the thread doesn't make the call out to the url. I also never see the log events that are written inside the HttpWebResponse using statement. I'm not sure what is going on, any help please?
HttpWebRequest urlRequest = (HttpWebRequest)WebRequest.Create(url);
urlRequest.Method = "POST";
byte[] data = Encoding.ASCII.GetBytes(JSON);
urlRequest.ContentLength = data.Length;
urlRequest.ContentType = "application/json";
ThreadPool.QueueUserWorkItem(o =>
{
try
{
new Logger().Info("data length = " + data.Length.ToString());
new Logger().Info(JSON);
new Logger().Info("Before posting to ERPFullAppointmentCheckout controller");
using (Stream stream = urlRequest.GetRequestStream())
{
stream.Write(data, 0, data.Length);
new Logger().Info("Before using HttpWebResponse");
using (HttpWebResponse response = (HttpWebResponse)urlRequest.GetResponse())
{
new Logger().Info("Inside using HttpWebResponse");
string receivedresponse = new StreamReader(response.GetResponseStream()).ReadToEnd();
string statuscode = response.StatusCode.ToString();
new Logger().Info("Response from POST: " + (String.IsNullOrEmpty(receivedresponse) ? "" : receivedresponse));
new Logger().Info("Status Code: " + statuscode);
}
}
new Logger().Info("After posting to ERPFullAppointmentCheckout controller");
}
catch (Exception ex)
{
new Logger().Error("Error posting to ERPFullAppointmentCheckout controller", ex);
}
});
Use:
HostingEnvironment.QueueBackgroundWorkItem
Instead of:
ThreadPool.QueueUserWorkItem
Look at these 2 links for more information on the difference...
https://blog.mariusschulz.com/2014/05/07/scheduling-background-jobs-from-an-asp-net-application-in-net-4-5-2
https://blogs.msdn.microsoft.com/webdev/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/

HttpWebResponse.GetResponse hangs in c#

I have the following code:
string url = string.Format("http://{0}:{1}/{2}/xml",Address.Host,Address.Port,Address.ContextRoot);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.UserAgent = "Foo";
req.ContentType = "text/xml; charset=\"UTF-8\"";
req.KeepAlive = false;
using (Stream reqStream = req.GetRequestStream())
{
SoapEnvelope s = new SoapEnvelope(Address, null);
XmlDocument xmlDoc = s.GenerateXml(message);
xmlDoc.Save(reqStream);
}
result = ReceiveAnswer(req);
private string ReceiveAnswer(HttpWebRequest req)
{
using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
using (Stream resStream = res.GetResponseStream())
using (StreamReader reader = new StreamReader(resStream))
{
if (res.StatusCode != HttpStatusCode.OK)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Failed to post data to http://{0}:{1}", Address.Host, Address.Port).AppendLine();
sb.AppendFormat("Response: {0} {1}", res.StatusCode, res.StatusDescription);
res.Close();
throw new WebException(sb.ToString());
}
String resData = reader.ReadToEnd();
return resData;
}
}
This code works fine, when I'm connecting to an existing server, but I've just tested, that if the server I specify does not exist then this part: (HttpWebResponse)req.GetResponse() will hang. I expected to get a webexception or something in this scenario, because I want to catch it.
I've read it somewhere that this Response has a timeout of 100 seconds, I've waited more than that, but nothing happened. Then I set the Timeout property to 15 seconds, but that didn't help either.
Anyone knows what should I do?
There was no problem with my code, an other part of the company's code causes the problem.
Be very careful with what you're doing.
Timeout method does not apply to the time waiting for the response to be caught.
Timeout counts for the entire life of your connection (meaning request + response).
If you're then setting a too-low timeout time, your program will never catch it. Maybe you could try to raise the Timeout number?

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.

Service HTTP Post is receiving "Existing Connection Was Forcibly Closed"

I have a windows service that I am trying to get running on a server. It just posts data to a php page and has further logic based on the response back. This works 100% on my machine and 100% on the server WHEN Anonymous Authenication is turned on for the website(IIS).
What I want to accomplish is to run the site with Windows Authenication turned ON and have my service still work... except when I try this I receive a nice EventLog entry.
"System.IO.IOException: Unable to read data from the transport
connection: An existing connection was forcibly closed by the remote
host"
I am running the service under an account that has all required permissions. So I understand that "CredentialCache.DefaultCredentials" should use this account for authentication( I am not receiving a 401 error ,but not ruling it out )
Below is my HttpPost code, I have set quite a few options from other posts trying to find a solution.
string postData = xml;
//--------------
HttpRequestCachePolicy policy = new HttpRequestCachePolicy MontgP02(HttpRequestCacheLevel.NoCacheNoStore);
HttpWebRequest.DefaultCachePolicy = policy;
byte[] buffer = Encoding.UTF8.GetBytes(postData);
//Initialisation
System.Net.ServicePointManager.Expect100Continue = false;
HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create(url);
//Credentials
WebReq.UseDefaultCredentials = true;
WebReq.PreAuthenticate = true;
WebReq.Credentials = CredentialCache.DefaultCredentials;
//Request Settings
WebReq.ProtocolVersion = HttpVersion.Version11;
//WebReq.ServicePoint.ConnectionLimit = 1;
WebReq.Method = "POST";
WebReq.ContentType = "application/x-www-form-urlencoded";
//The length of the buffer
WebReq.ContentLength = buffer.Length;
//Set timeout
WebReq.Timeout = 25000;
//Use Proxy or Not
if (useproxy == "ON")
{
WebProxy myProxy = new WebProxy();
// Create a new Uri object.
Uri newUri = new Uri(proxy);
// Associate the new Uri object to the myProxy object.
myProxy.Address = newUri;
WebReq.Proxy = myProxy;
}
try
{
//Send Data
using (Stream requestStream = WebReq.GetRequestStream())
{
// write to stream
//write, and close.
requestStream.Write(buffer, 0, buffer.Length);
}
}
catch (WebException ex) {
MessageLog("ERROR: Sending Data : " + ex.ToString() + ":", "ERROR");
}
//Get Response
try
{
using (System.Net.WebResponse response = WebReq.GetResponse())
{
Stream Answer = response.GetResponseStream();
// read from stream
StreamReader _Answer = new StreamReader(Answer);
PostResponse = _Answer.ReadToEnd();
}
}
catch (WebException ex)
{
MessageLog("ERROR: Receiving Response : " + ex.ToString() + ":" , "ERROR");
}
}
catch (WebException ex)
{
MessageLog("ERROR Posting " + ex.ToString() + ":" + PostResponse, "ERROR");
}
}
I understand from the error that the server is cutting the connection before I can complete the request. This happens everytime on the server negating thoughts of timeouts I would think.
Having looked around other fourms, I am at a loss , having tried other variations etc the fact that it does work fine with authenication off leads me to think it may be a setting in IIS or something else down the authenication route.
Any insight welcome

Categories