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?
Related
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.
So I'm following the WingTip Toy tutorial, and I know its sort of old but it was error free until I got to the point where I needed to checkout with PayPal using the sandbox developing tool
This is the code where the error occurs
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
And this is the error im getting when i run it
[ProtocolViolationException: You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.]
Please note I'm a beginner
Edit: The full code is here
public string HttpCall(string NvpRequest)
{
string url = pEndPointURL;
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost);
}
}
catch (Exception)
{
// No logging for this tutorial.
}
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
}
objRequest.ContentLength = strPost.Length;
What are you trying to do here? The framework sets the content length automatically. The content length is in bytes but you have given the number of characters.
That's why the error complains: You have written a different number of characters than you said you would write.
Delete that line.
Your code would become a lot simpler if you used HttpClient. Should be about 5 lines.
I've got a piece of code the goes out and does an HttpWebRequest to Google Wallet. The code works just fine on all my machines, except for this one computer at work that I'm on right now. The Internet on this computer works just fine (as I'm using it right now to type this question) and we have no proxy server at work.
The problem is that it just hangs. It doesn't even timeout. It just hangs with no error message or anything and I have to force close it. Here is the code:
private static string GetLoginHtml()
{
var request = (HttpWebRequest)WebRequest.Create(LoginUrl);
var cookieJar = new CookieContainer();
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = cookieJar;
using (var requestStream = request.GetRequestStream())
{
string content = "Email=" + Username + "&Passwd=" + Password;
requestStream.Write(Encoding.UTF8.GetBytes(content), 0, Encoding.UTF8.GetBytes(content).Length);
using (var sr = new StreamReader(request.GetResponse().GetResponseStream()))
{
string html = sr.ReadToEnd();
string galxValue = ParseOutValue(html, "GALX");
return GetLoginHtml2(galxValue, cookieJar);
}
}
}
Stepping through the code on the Visual Studio debugger, I know that it hangs when it hits the following line:
using (var sr = new StreamReader(request.GetResponse().GetResponseStream()))
Specifically, the request.GetResponse() part is what's hanging. Running Fiddler, all I see is a gray entry that looks like this:
3 200 HTTP Tunnel to accounts.google.com:443 0
There is nothing else. No response body. Do anyone have any suggestions on what could be going on? The fact that its happening on just this one computer tells me that it may not be a programming issue.
I finally figured out the issue with this. I'm posting this answer in hopes it might help someone else with some inevitable head scratching in the future.
Here is my working code now:
private static string GetLoginHtml()
{
var request = (HttpWebRequest)WebRequest.Create(LoginUrl);
var cookieJar = new CookieContainer();
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = cookieJar;
using (var requestStream = request.GetRequestStream())
{
string content = "Email=" + Username + "&Passwd=" + Password;
requestStream.Write(Encoding.UTF8.GetBytes(content), 0, Encoding.UTF8.GetBytes(content).Length);
}
using (var sr = new StreamReader(request.GetResponse().GetResponseStream()))
{
string html = sr.ReadToEnd();
string galxValue = ParseOutValue(html, "GALX");
return GetLoginHtml2(galxValue, cookieJar);
}
}
My guess is that my requestStream wasn't being garbage collected and closed before getting the response stream. I think the response stream was being open and read before the request stream finished writing its bytes. Silly .NET garbage collector
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.
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;
}