I have a windows app that sends a json to a website every 3 minutes. But I am not getting through to the web and I am not catching any exceptions which is strange. How it works.
Timer set to go off every 3min(180000milisecs)
timer1 = new System.Timers.Timer(180000);
timer1.Elapsed += new System.Timers.ElapsedEventHandler(onTimerEvent);
timer1.Start();
The timer calls a backround worker to run the update
//run the worker job every 3 minutes
private void onTimerEvent(object sender, EventArgs e)
{
minerQuery.RunWorkerAsync();
}
The worker calls the function to gather the data and then send the json
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string user_worker = textBox2.Text.Trim().ToLower() + ":" + textBox1.Text.Trim().ToLower();
bool logging = false;
if (this.radioButton1.Checked)
{
logging = true;
}
WorkerUpdate workerUpdate = new WorkerUpdate();
workerUpdate.update(user_worker, logging);
}
Once the function gathers the data in sends the request using this function
static void HttpPutRequest(string Json, bool logging)
{
try{
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https:/blah/here/update");
Request.ContentType = "application/json";
Request.Method = "PUT";
Request.Timeout = 120000; //not sure if correct
Stream dataStream = Request.GetRequestStream();
byte[] bytes = Encoding.UTF8.GetBytes(Json);
Request.ContentLength = bytes.Length;
dataStream.Write(bytes, 0, bytes.Length);
dataStream.Close();
HttpWebResponse response = (HttpWebResponse)Request.GetResponse();
Stream RdataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(RdataStream);
if (logging)
{
Logger("Sending JSON: " + Json);
Logger("To URL: " + Request.ToString());
Logger("Status: " + ((HttpWebResponse)response).StatusDescription);
Logger("Response: " + reader.ReadToEnd());
}
reader.Close();
RdataStream.Close();
response.Close();
}
catch (WebException we)
{
if (logging)
{
Logger("Web Expection Catch: " + we.ToString());
WebExceptionStatus status = we.Status;
if (status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse http = (HttpWebResponse)we.Response;
Logger("The Server returned protocal Error: " + (int)http.StatusCode + " - " + http.StatusCode);
}
}
}
}
When I run my program it works and I see logging for other events. But when it comes to the http put request none of the logging in this code is every printed onto the screen. So I know something is going wrong. I put this code together from the MSDN examples which aren't the best.
Where I think the problem may be
Not sure if running this function under a timer event and a background worker is suppressing my expections?
Code to send http is not correct
HttpPutRequest is called here
this.wun = user_worker;
this.a = Convert.ToInt32(FindKey(SummaryQuery, "Accepted"), US);
this.r = Convert.ToInt32(FindKey(SummaryQuery, "Rejected"), US);
this.he = Convert.ToInt32(FindKey(SummaryQuery, "Hardware Errors"), US);
this.gs = gpuList.ToArray();
//create JSON from the workerUpdate object
string JSON = JsonConvert.SerializeObject(this);
//send to website
HttpPutRequest(JSON, logging);
Update
Running the code in debug mode I found this exception.
System.InvalidOperationException
from this line of code
Request.ContentLength = bytes.Length;
The InvalidOperationException is caused by calling GetRequestStream() before setting ContentLength
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.contentlength(v=vs.110).aspx
ContentLength: InvalidOperationException is thrown if the request has
been started by calling the GetRequestStream, BeginGetRequestStream,
GetResponse, or BeginGetResponse method.
Try:
byte[] bytes = Encoding.UTF8.GetBytes(Json);
Request.ContentLength = bytes.Length;
Stream dataStream = Request.GetRequestStream();
Edit:
As for the Logging issue is could be because you are accessing UI controls in the BackgroundWorkers thread. and because you are only catching WebExceptions the error will not be logged.
Try adding all exceptions also in your try catch to be sure
Example:
try
{
// all my cool logic
}
catch (WebException we)
{
// log WebException
}
catch (Exception ex)
{
// log other exceptions
}
Related
I have a program that has a lot of HttpWebRequest calls in it. It deals a lot with external API requests to various streaming platforms (Twitch, Hitbox, Beam, YouTube). All of my requests seem to work fine.
Here is an example of one of my requests:
private void save_Click(object sender, RoutedEventArgs e)
{
string postUrl = "https://api.twitch.tv/kraken/channels/" + this.channelID;
string postData = "channel[status]=" + Uri.EscapeDataString(status.Text) +
"&channel[game]=" + Uri.EscapeDataString(game.Text);
byte[] postByte = Encoding.UTF8.GetBytes(postData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUrl);
request.Method = "PUT";
request.Accept = "application/vnd.twitchtv.v5+json";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postByte.Length;
request.Headers.Add("Authorization", "OAuth " + password.Password);
request.Headers.Add("Client-ID", this.clientID);
request.Timeout = 15000;
try
{
Stream putStream = request.GetRequestStream();
putStream.Write(postByte, 0, postByte.Length);
putStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}
catch (WebException err)
{
MessageBox.Show("Unable to update channel information:\n" + err.Message);
}
}
However, there is an issue that if a request fails (such as a momentary internet hiccup), and the try-catch responds with an error due to a timeout, then no future HttpWebRequests will work until I restart my program.
This only happens if the error catch is initiated by a timeout.
Is there a reason why this happens and how can I fix it?
It's most likely being caused by resources that are not properly released causing locks.
Change your code to maybe call abort on HttpWebRequest on WebException and maybe also wrap the HttpWebResponse and putStream in a using statement.
private void save_Click(object sender, RoutedEventArgs e)
{
string postUrl = "https://api.twitch.tv/kraken/channels/" + this.channelID;
string postData = "channel[status]=" + Uri.EscapeDataString(status.Text) +
"&channel[game]=" + Uri.EscapeDataString(game.Text);
byte[] postByte = Encoding.UTF8.GetBytes(postData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUrl);
request.Method = "PUT";
request.Accept = "application/vnd.twitchtv.v5+json";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postByte.Length;
request.Headers.Add("Authorization", "OAuth " + password.Password);
request.Headers.Add("Client-ID", this.clientID);
request.Timeout = 15000;
try
{
using (Stream putStream = request.GetRequestStream())
{
putStream.Write(postByte, 0, postByte.Length);
using (var response = (HttpWebResponse) request.GetResponse())
{
//assign the response result to a variable else it's getting disposed
}
}
}
catch (WebException err)
{
request.Abort();
MessageBox.Show("Unable to update channel information:\n" + err.Message);
}
}
I'm using WinForms and accessing my Restful webservice. For some reason the code after a while breaks, by giving the timeout error while connecting to the server.
The problem might also be due to my code design.
Here's my Restful client class
public class Restful
{
public string auth = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes("MyUserName:MyPassword"));
public string POST(string parameters)
{
var request = (HttpWebRequest)WebRequest.Create("http://myserverdomain.com/api/webservice/someMethod");
byte[] byteArray = Encoding.UTF8.GetBytes(parameters);
request.Method = WebRequestMethods.Http.Post;
request.Headers["Authorization"] = this.auth;
request.ContentLength = byteArray.Length;
request.ContentType = "application/x-www-form-urlencoded";
Stream postStream = null;
try
{
// ERROR IS IN THIS LINE
postStream = request.GetRequestStream();
}
catch (WebException ex)
{
// I'm kind of creating an hack here..which isn't good..
if (ex.Status.ToString() == "ConnectFailure")
{
System.Threading.Thread.Sleep(1000);
this.POST(parameters);
}
}
if (postStream == null)
return string.Empty;
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
using (var response = (HttpWebResponse)request.GetResponse())
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
return responseValue;
using (var responseStream = response.GetResponseStream())
if (responseStream != null)
using (var reader = new StreamReader(responseStream))
responseValue = reader.ReadToEnd();
return responseValue;
}
}
}
I'm receiving the error (after a few successfully send items):
Unable to connect to remote server
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond MyServerIpAddress
Sometimes I send thousands of items to the server, sometimes I only send 2 or 4. So I call this POST function within a loop.
try
{
foreach (app.views.Documents doc in DocumentsView)
{
var parameters = "key=" + doc.key;
parameters += "¶m1=" + doc.param1 + "¶m2=" + doc.param2;
/*
* Validates the response of Restful service.
* The response is always in JSON format.
*/
if (response(Restful.POST(parameters)) == false)
{
MessageBox.Show("Error while sending the ID: " + doc.id.ToString());
break;
};
}
}
catch (Exception ex)
{
MessageBox.Show("Error while sending documents: " + ex.Message);
}
You can change the default timeout of your HttpWebRequest to be some thing larger than the default, for example:
request.Timeout = 120000;
I think the default is 100 seconds.
You can also check this adjusting-httpwebrequest-connection-timeout-in-c-sharp
taking the failure at face value, it says that the remote machine didnt respond. Most likely causes
wrong name or ip address
windows firewall is on on the remote machine
I have the following code :
public static QHttpResponse Execute(QHttpRequest request)
{
//Setup the request
HttpWebRequest webrequest = (HttpWebRequest) WebRequest.Create(request.GetFinalUrl());
webrequest.AllowAutoRedirect = request.IsAllowRedirects;
webrequest.Method = request.Method;
webrequest.Accept = "application/json, text/javascript;q=0.9, */*;q=0.5";
webrequest.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
//request.Host is set automatically
webrequest.UserAgent = request.UserAgent;
if (!String.IsNullOrEmpty(request.Referrer))
webrequest.Referer = request.Referrer;
webrequest.Timeout = 50000;
webrequest.KeepAlive = false;
webrequest.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Revalidate);
webrequest.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
if (request.IsAjax)
{
webrequest.Headers.Add("X-Request", "JSON");
webrequest.Headers.Add("X-Requested-With", "XMLHttpRequest");
webrequest.Headers.Add("X-Prototype-Version", "1.7");
}
// Cookies
webrequest.CookieContainer = request.Cookies;
// Write the data to the body for POST and other methods
if (request.IsMethodPost())
{
byte[] dataBytes = Encoding.UTF8.GetBytes(request.GetDataParamString());
webrequest.ContentLength = dataBytes.Length;
using (Stream requestStream = webrequest.GetRequestStream())
requestStream.Write(dataBytes, 0, dataBytes.Length);
}
// Get the response
HttpWebResponse webresponse;
try
{
webresponse = webrequest.GetResponse() as HttpWebResponse;
}
catch (WebException wex)
{
if(request.IsBypassError)
webresponse = wex.Response as HttpWebResponse;
else
throw;
}
// Read to QHttpResponse object
QHttpResponse response = new QHttpResponse();
response.StatusCode = webresponse.StatusCode;
response.NewCookies = webresponse.Cookies;
using (Stream responseStream = webresponse.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
response.Reply = reader.ReadToEnd();
webresponse.Close();
return response;
}
I have this code run multiple times from various locations and randomly (Every couple of hours), it hangs at this line :
webresponse = webrequest.GetResponse() as HttpWebResponse;
I tried setting webrequest.KeepAlive = false;, but I continued to receive the error.
I'd like any available help on solving this, thanks in advance.
EDIT : I'd like to add that this code is executed from two threads. Occasionally they may connect to the same host, but only from these 2 threads. Also, as I see, the response is closed appropriately.
EDIT 2 : Visual studio's debugger says the execution is really stuck at System.dll!System.Net.Sockets.Socket.Receive.
EDIT 3 : In an attempt to see exactly what was causing the bug, I modified the "Get the response" code from above to
// Get the response
HttpWebResponse webresponse = null;
try
{
webresponse = webrequest.GetResponse() as HttpWebResponse;
}
catch (WebException wex)
{
Console.WriteLine("Time : " + DateTime.Now);
Console.WriteLine("Thread name : " + Thread.CurrentThread.Name);
Console.WriteLine("Exception : " + wex);
Console.WriteLine("Exc msg : " + wex.Message);
Console.WriteLine("Url : " + request.GetFinalUrl());
if (request.IsBypassError)
webresponse = wex.Response as HttpWebResponse;
else
{
if (webresponse != null)
{
webresponse.Close();
webresponse.Dispose();
}
throw;
}
}
I received this output :
Time : 5/11/2015 3:13:35 AM
Thread name : BOT A
Exception : System.Net.WebException: The remote server returned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
at Gameloop.Util.Web.QWebClient.Execute(QHttpRequest request) in e:\Visual Studio - Workspace\Gameloop.Util\Gameloop.Util\Web\QWebClient.cs:line 52
Exc msg : The remote server returned an error: (500) Internal Server Error.
Url : https://website1.com/url/path/to/something (I changed this)
This was the only displayed error and was encountered by thread "BOT A". However, this was not the url the threads appear to have actually frozen at. "BOT A" was actually frozen at 12:00pm at website2.com and "BOT B" was actually frozen at 7:00am at website3.com. I doubt the hanging has much to do with the exception since the requests would have been made a large number of times after that before the actual hang.
My first inclination is that you may need to dispose of your HttpWebResponse. Normally you might wrap that in a using block, but since you have two places where webresponse might be assigned, you might just want to dispose it explicitly, like this.
webresponse.Close();
webresponse.Dispose();
I would start there.
Just add below in the try block:
httpWReq.Timeout = 3000;
public int loginEmail(string email, string password)
{
HttpWebRequest request = null;
string responseStr = null;
string Email = email;
string Pass = password;
UTF8Encoding encoding = new UTF8Encoding();
string postData = "PostData";
byte[] data = encoding.GetBytes(postData);
request = (HttpWebRequest)WebRequest.Create("url");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.AllowAutoRedirect = false;
request.KeepAlive = false;
request.Proxy = null;
request.ServicePoint.ConnectionLimit = 1000;
request.ContentLength = data.Length;
request.Timeout = 5000;
request.ServicePoint.ConnectionLeaseTimeout = 5000;
request.ServicePoint.MaxIdleTime = 5000;
using (Stream stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
responseStr = response.Headers["Set-Cookie"];
}
}
catch
{
return 1;
}
string[] cooktemp;
string[] seperatortemp = new string[] { ";" };
cooktemp = responseStr.Split(seperatortemp, StringSplitOptions.None);
LoginHeaders[0] = cooktemp[0] + ";";
return 0;
}
This code runs just fine, but sometimes the request does not get a response back. When the request doesn't get a response back the program will hang and then finally it will give a timeout error that crashes the program. All I am trying to do right now is just catch the timeout error so I can handle it, but nothing seems to be catching it.
It is most likely timing out in GetRequestStream(). The documentation specifically states that it may throw WebException if the time-out period for the request expired.
So include that block of code inside your try/catch and you should be able to catch it.
This is an old thread, but an issue which I also hit today.
What I didn't realise is that if you have a web service which, say, attempts to write to a file which is locked... then having the code in a simple try..catch is not enough.
You must specifically have a catch which handles WebExceptions.
try
{
// Run your web service code
}
catch (WebException ex)
{
// Handle a WebException, such as trying to write to a "locked" file on the network
}
catch (Exception ex)
{
// Handle a regular Exception
}
I always thought that a WebException was a type of Exception, so these would get caught by this catch handler:
catch (Exception ex)
{
// Handle a regular Exception
}
It doesn't.
So to avoid your code throwing "Request timed out" messages, with no suggestion about what caused them, do remember to add these second catch handler.
Btw, on my web services tutorial, here's the code I recommend, which looks out for Exceptions, and returns them in the Response header:
try
{
// Put your code in here
}
catch (WebException ex)
{
// Return any exception messages back to the Response header
OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
response.StatusDescription = ex.Message.Replace("\r\n", "");
return null;
}
catch (Exception ex)
{
// Return any exception messages back to the Response header
OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
response.StatusDescription = ex.Message.Replace("\r\n", "");
return null;
}
try { ... }
catch (System.Net.WebException sne)
{
MessageBox.Show(req.Timeout.ToString());
}
I think the timeout will always be "5000" no matter what.
If you tell it "timeout is 5 seconds" it will always try for 5 seconds before giving up.
I tried using WebRequest.GetResponse() on my developement machine(XP) and it works properly and I can read the response stream from the URL, but the compiled code fails on two client machines(Windows 7) when the URL is identical. The WebException.Status is "The network request is not supported." Why would that occur whan trying to access the same URL? The WebException is fired by the GetResponse method. In the catch clause, the response object and the WebException.Response objects are both null. What can I do to further diagnose the problem?
WebRequest request = null;
HttpWebResponse response = null;
Stream dataStream = null;
StreamReader reader = null;
String responseFromServer = string.Empty;
string http = string.Empty;
int timeOut = 30000;
string errorMsg = string.Empty;
http = this.URLstring;
bool error = false;
try
{
request = System.Net.WebRequest.Create(http);
request.Timeout = timeOut;
response = (System.Net.HttpWebResponse)request.GetResponse();
}
catch (System.Net.WebException wex)
{
error = true;
errorMsg = wex.Message + " " + wex.Status.ToString();
if (wex.Response != null)
{
WebHeaderCollection hdrs = wex.Response.Headers;
for (int i = 0; i < hdrs.Count; i++)
errorMsg += Environment.NewLine + hdrs.Keys[i] + ", " + hdrs[i];
}
}
// Code to read the response stream goes here. it works on development machine.
It could be a privileges matter. To test that, run the App under Win7 'As Administrator'