I have an strange problem. My .NET DataController send a response to an Java server (REST). All works fine, but when I send a response very often, suddenly the GetResponse method not coming back just hangs.
I don't know what's the problem is.
Here is my code
ServicePointManager.DefaultConnectionLimit = 20;
public string HttpGet(string url, string requestAccept)
{
if(string.IsNullOrEmpty(url))
throw new Exception("HttpGet: no REST service URL provided");
if(string.IsNullOrEmpty(requestAccept))
requestAccept = defaultRequestAccept;
if(!url.Equals("pc/alive"))
{
if(string.IsNullOrEmpty(SessionId))
{
if(string.IsNullOrEmpty(Authorization()))
throw new WebException("HttpGet: no login");
}
}
int tries = RestAccessData.MaxReconnect;
string result = string.Empty;
do
{
try
{
var request = NewWebRequest(url, "GET", false, true, requestAccept);
using(var response = request.GetResponse() as HttpWebResponse)
{
UpdateSessionId(response);
HttpStatusCode statusCode = response.StatusCode;
LOG.Debug("...StatusCode: {0} ({1})", (int) response.StatusCode, response.StatusDescription);
if((int) response.StatusCode < 500)
lastContactWithServer = DateTime.Now.Ticks;
switch(statusCode)
{
// Informational 1xx
case HttpStatusCode.Continue: // 100
case HttpStatusCode.SwitchingProtocols: // 101
throw new HttpResponseException(response);
// Successful 2xx
case HttpStatusCode.OK: // 200
result = ReadContent(response);
response.Close();
return (result);
case HttpStatusCode.NoContent: // 204 The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.
response.Close();
return (string.Empty);
case HttpStatusCode.Created: // 201
case HttpStatusCode.NonAuthoritativeInformation: // 203
result = ReadContent(response);
throw new HttpResponseException(response, result);
case HttpStatusCode.Accepted: // 202 The request has been accepted for processing, but the processing has not been completed.
case HttpStatusCode.ResetContent: // 205 The server has fulfilled the request and the user agent SHOULD reset the document view which caused the request to be sent.
case HttpStatusCode.PartialContent: // 206 The server has fulfilled the partial GET request for the resource.
throw new HttpResponseException(response);
case HttpStatusCode.Unauthorized:
throw new HttpResponseException(response);
default:
throw new HttpResponseException(response);
}
}
}
catch(WebException ex)
{
HandleWebException(ex);
}
catch(HttpResponseException ex)
{
throw ex;
}
catch(SystemException ex)
{
LOG.Error(ex, "caused a(n) {0}", ex.GetType().Name);
}
catch(Exception ex)
{
LOG.Warn(ex, "HttpGet: An error occured while trying to contact the server. Reason: {0}", ex.Message);
throw new UserException("An error occured while trying to contact the server.", ex);
}
}
while(0 < tries--);
return (string.Empty);
}
private HttpWebRequest NewWebRequest(string urlAsString, string requestType, bool withContentType, bool applicationJson, string requestAccept)
{
urlAsString = string.Format("{0}{1}", RestAccessData.GetUrl(), EncodeUrl(urlAsString));
Uri url;
if(!Uri.TryCreate(urlAsString, UriKind.Absolute, out url))
throw new NotSupportedException("url is not compatible");
LOG.Info("RESTUrl {0}", urlAsString);
try
{
var request = HttpWebRequest.Create(url) as HttpWebRequest;
if(!string.IsNullOrEmpty(SessionId))
{
CookieContainer cookies = new CookieContainer();
Cookie cookie = new Cookie
{
Name = "JSESSIONID",
Value = SessionId,
Domain = url.Host
};
cookies.Add(cookie);
request.CookieContainer = cookies;
}
request.Timeout = RestAccessData.Timeout;
request.Method = requestType;
request.AllowAutoRedirect = true;
request.AllowWriteStreamBuffering = true;
request.KeepAlive = false;
request.ContentLength = 0;
request.Headers["Accept-Charset"] = "utf-8";
request.Accept = requestAccept;
request.UserAgent = LvsClient;
if(withContentType)
request.ContentType = applicationJson ? defaultApplicationJson : defaultApplicationWwwForm;
if(!string.IsNullOrEmpty(credential.UserName) && !string.IsNullOrEmpty(credential.Password))
request.Headers["Authorization"] = string.Format("Basic {0}", Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", credential.UserName, credential.Password))));
return (request);
}
catch(Exception ex)
{
throw new UserException(TH.Translate("NewWebRequest caused an error"), ex);
}
}
Any ideas where the problem is?
This line is making me uncomfortable:
using(var response = request.GetResponse() as HttpWebResponse)
If the response is not an HttpWebResponse then it will never be disposed - the as operator will give you `null.
I found a solution. Very useful is this MSDN article about Understanding MaxServicePointIdleTime and DefaultConnectionLimit. After I play with MaxServicePointIdleTime property and read this comment
change the connection limit at any time
I found a good balance between connection alive and connection close. My client works fine after playing with MaxServicePointIdleTime and DefaultConnectionLimit.
Related
This is my method, to which I am passing the url to check if it's active.
The link is being activated on the wowza service so it takes some time until it's "alive"
GetResponse is returning the 404 Error because the url is not reached.
Is there a way to get the timeout instead of 404 error if the url is not alive after specified time?
public async Task<IActionResult> GetLinkIsAlive([FromQuery] string url, [FromQuery] int timeout)
{
HttpWebResponse webResponse;
try
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Timeout = timeout;
webRequest.Method = "GET";
webResponse = webRequest.GetResponse() as HttpWebResponse;
return Ok(webResponse.StatusCode);
}
catch (WebException ex)
{
return BadRequest(ex.Message);
}
}
You can use connection pooling.
It’s using IHttpClientFactory that helps to maintain the pooling and lifetime of clients
In your startup class :
services.AddHttpClient<NameofyourService, NameofyourService>()
.AddTransientHttpErrorPolicy(
p => p.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)
}));
It requires Microsoft.Extensions.Http.Polly
You need to use HttpClient for your service. All added configurations will apply automatically.
My solution to this was calling the link in the while loop every 1s and await the whole Task.
private async Task<bool> IsLiveStreamAlive(string streamUrl, int retriesCount = 30)
{
try
{
bool res = false;
HttpClient client = new HttpClient();
Uri uri = new Uri(streamUrl);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
var request = new HttpRequestMessage(HttpMethod.Get, uri);
while (retriesCount > 1)
{
await Task.Delay(1000);
retriesCount--;
HttpResponseMessage httpResponse = await client.GetAsync(uri);
res = httpResponse.StatusCode == HttpStatusCode.OK ? true : false;
if (res)
{
Log.Info(string.Format("Stream alive: {0}", streamUrl));
break;
}
}
return res;
}
catch (WebException ex)
{
Log.Error(ex);
}
return false;
}
I am trying to get a response from google in c# to get a token.
I am using the url - https://accounts.google.com/o/oauth2/token.
My code is the following;
public WebResponse GetResponse(string url, params GoogleParameter[] parameters)
{
//Format the parameters
string formattedParameters = string.Empty;
foreach (var par in parameters)
formattedParameters += string.Format("{0}={1}&", par.Name, par.Value);
formattedParameters = formattedParameters.TrimEnd('&');
//Create a request with or without parameters
HttpWebRequest request = null;
if (formattedParameters.Length > 0)
{
//string debug = (string.Format("{0}?{1}", url, formattedParameters));
request = (HttpWebRequest)WebRequest.Create(string.Format("{0}?{1}", url, formattedParameters));
}
else
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
//Add the authentication header.
request.Headers.Add("Authorization", "GoogleLogin auth=" + auth);
HttpWebResponse response = null;
//Get the response, validate and return
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
if (response == null)
throw new Exception("No Response from Google");
else if (response.StatusCode != HttpStatusCode.OK)
throw new Exception("Incorrect Response: " + response.StatusCode + " " + response.StatusDescription);
return response;
}
The line
response = (HttpWebResponse)request.GetResponse();
is giving me the 405 Error Method Not Allowed.
I have tried for the past two days to fix this but nothing, can anyone see where I have went wrong?
Thanks
I am attempting to make a simple function that verifies that a specific file exists on a website.
The web request is set to head so I can get the file length instead of downloading the entire file, but I get "Unable to connect to the remote server" exception.
How can I verify a file exists on a website?
WebRequest w;
WebResponse r;
w = WebRequest.Create("http://website.com/stuff/images/9-18-2011-3-42-16-PM.gif");
w.Method = "HEAD";
r = w.GetResponse();
edit: My bad, turns out my firewall was blocking http requests after I checked the log.
It didnt prompt me for an exception rule so I assumed it was a bug.
I've tested this and it works fine:
private bool testRequest(string urlToCheck)
{
var wreq = (HttpWebRequest)WebRequest.Create(urlToCheck);
//wreq.KeepAlive = true;
wreq.Method = "HEAD";
HttpWebResponse wresp = null;
try
{
wresp = (HttpWebResponse)wreq.GetResponse();
return (wresp.StatusCode == HttpStatusCode.OK);
}
catch (Exception exc)
{
System.Diagnostics.Debug.WriteLine(String.Format("url: {0} not found", urlToCheck));
return false;
}
finally
{
if (wresp != null)
{
wresp.Close();
}
}
}
try it with this url: http://www.centrosardegna.com/images/losa/losaabbasanta.png then modify the image name and it will return false. ;-)
try
{
WebRequest request = HttpWebRequest.Create("http://www.microsoft.com/NonExistantFile.aspx");
request.Method = "HEAD"; // Just get the document headers, not the data.
request.Credentials = System.Net.CredentialCache.DefaultCredentials;
// This may throw a WebException:
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
// If no exception was thrown until now, the file exists and we
// are allowed to read it.
MessageBox.Show("The file exists!");
}
else
{
// Some other HTTP response - probably not good.
// Check its StatusCode and handle it.
}
}
}
catch (WebException ex)
{
// Cast the WebResponse so we can check the StatusCode property
HttpWebResponse webResponse = (HttpWebResponse)ex.Response;
// Determine the cause of the exception, was it 404?
if (webResponse.StatusCode == HttpStatusCode.NotFound)
{
MessageBox.Show("The file does not exist!");
}
else
{
// Handle differently...
MessageBox.Show(ex.Message);
}
}
I am working on a desktop application developed in C# (.NET environment).
This application connects to remote server using HttpWebRequest. If due to any reason my PC is disconnected from the internet and I re-connect it my application always gives request timeout for HttpWebRequest until I restart my whole application and if I again add new thread to my application after network d/c it works fine.
Is there any way to reset my network or anyone can tell me how does it work?
//my code is..
public String request(String add, String post, int time, String reff, int id, int rwtime)
{
try
{
if (rwtime == 0)
{
rwtime = 100000;
}
string result = "";
string location = "";
// Create the web request
HttpWebRequest req = WebRequest.Create(add) as HttpWebRequest;
req.ReadWriteTimeout = rwtime;
req.KeepAlive = true;
req.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
req.Accept = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
req.ContentType = "application/x-www-form-urlencoded";
req.Timeout = time;
req.Referer = reff;
req.AllowAutoRedirect = false;
req.CookieContainer = statictk.cc[id];
req.PreAuthenticate = true;
if (post != "")
{
req.Method = "POST";
string postData = post;
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(postData);
// Set the content type of the data being posted.
req.ContentType = "application/x-www-form-urlencoded";
// Set the content length of the string being posted.
req.ContentLength = byte1.Length;
Stream newStream = req.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);
newStream.Close();
}
else
{
req.Method = "GET";
}
// Get response
try
{
HttpWebResponse response = req.GetResponse() as HttpWebResponse;
// Get the response stream
location = response.GetResponseHeader("Location");
if (location == "")
{
Stream responseStream = response.GetResponseStream();
if (response.ContentEncoding.ToLower().Contains("gzip"))
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
else if (response.ContentEncoding.ToLower().Contains("deflate"))
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
StreamReader reader = new StreamReader(responseStream, Encoding.Default);
// Read the whole contents and return as a string
result = reader.ReadToEnd();
}
else
{
result = location;
}
response.Close();
if (result == "") result = "retry";
return result;
}
catch (Exception e)
{
log.store("errorinresponce", e.Message);
if (statictd.status[id] != "removed")
{
return "retry";
}
else
{
return "error";
}
}
}
catch(Exception f)
{
log.store("Networkerrorretry", f.Message);
if (f.Message == "The operation has timed out")
{
return "retry";
}
string ans = MessageBox.Show("There was a Network Error..Wish to Retry ?\nError msg : "+ f.Message, "Title", MessageBoxButtons.YesNo).ToString();
if (ans == "Yes")
return "retry";
else
{
Invoketk.settxt(id, "Not Ready");
return "error";
}
}
}
It sounds like your application is missing some error handling. A disconnect can happen at any time and your application should be able to handle it. Try to surround the network loop with a try-catch statement, and then catch for the different kinds of exceptions. Depending on what exception was thrown, you can then decide if you reconnect to the server silently or if you want to generate an error message.
I know I can locally, on my filesystem, check if a file exists:
if(File.Exists(path))
Can I check at a particular remote URL?
If you're attempting to verify the existence of a web resource, I would recommend using the HttpWebRequest class. This will allow you to send a HEAD request to the URL in question. Only the response headers will be returned, even if the resource exists.
var url = "http://www.domain.com/image.png";
HttpWebResponse response = null;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "HEAD";
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
/* A WebException will be thrown if the status of the response is not `200 OK` */
}
finally
{
// Don't forget to close your response.
if (response != null)
{
response.Close();
}
}
Of course, if you want to download the resource if it exists it would most likely be more efficient to send a GET request instead (by not setting the Method property to "HEAD", or by using the WebClient class).
If you want to just copy & paste Justin's code and get a method to use, here's how I've implemented it:
using System.Net;
public class MyClass {
static public bool URLExists (string url) {
bool result = false;
WebRequest webRequest = WebRequest.Create(url);
webRequest.Timeout = 1200; // miliseconds
webRequest.Method = "HEAD";
HttpWebResponse response = null;
try {
response = (HttpWebResponse)webRequest.GetResponse();
result = true;
} catch (WebException webException) {
Debug.Log(url +" doesn't exist: "+ webException.Message);
} finally {
if (response != null) {
response.Close();
}
}
return result;
}
}
I'll keep his observation:
If you want to download the resource, and it exists, it would be more efficient to send a GET request instead by not setting the Method property to "HEAD" or by using the WebClient class.
Below is a simplified version of the code:
public bool URLExists(string url)
{
bool result = true;
WebRequest webRequest = WebRequest.Create(url);
webRequest.Timeout = 1200; // miliseconds
webRequest.Method = "HEAD";
try
{
webRequest.GetResponse();
}
catch
{
result = false;
}
return result;
}
If you are using a unc path or a mapped drive, this will work fine.
If you are using a web address (http, ftp etc) you are better off using WebClient - you will get a WebException if it doesn't exist.
public static bool UrlExists(string file)
{
bool exists = false;
HttpWebResponse response = null;
var request = (HttpWebRequest)WebRequest.Create(file);
request.Method = "HEAD";
request.Timeout = 5000; // milliseconds
request.AllowAutoRedirect = false;
try
{
response = (HttpWebResponse)request.GetResponse();
exists = response.StatusCode == HttpStatusCode.OK;
}
catch
{
exists = false;
}
finally
{
// close your response.
if (response != null)
response.Close();
}
return exists;
}
I had the same problem to solve in asp.net core, I've solved with HttpClient
private async Task<bool> isFileExist(string url)
{
using (HttpClient client = new HttpClient())
{
var restponse = await client.GetAsync(url);
return restponse.StatusCode == System.Net.HttpStatusCode.OK;
}
}
My version:
public bool IsUrlExist(string url, int timeOutMs = 1000)
{
WebRequest webRequest = WebRequest.Create(url);
webRequest.Method = "HEAD";
webRequest.Timeout = timeOutMs;
try
{
var response = webRequest.GetResponse();
/* response is `200 OK` */
response.Close();
}
catch
{
/* Any other response */
return false;
}
return true;
}
WebRequest will waiting long time(ignore the timeout user set) because not set proxy, so I change to use RestSharp to do this.
var client = new RestClient(url);
var request = new RestRequest(Method.HEAD);
request.Timeout = 5000;
var response = client.Execute(request);
result = response.StatusCode == HttpStatusCode.OK;
Thanks for all answers.
And I would like to add my implementation which includes default state when we get errors, for specific cases like mine.
private bool HTTP_URLExists(String vstrURL, bool vResErrorDefault = false, int vTimeOut = 1200)
{
bool vResult = false;
WebRequest webRequest = WebRequest.Create(vstrURL);
webRequest.Timeout = vTimeOut; // miliseconds
webRequest.Method = "HEAD";
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)webRequest.GetResponse();
if (response.StatusCode == HttpStatusCode.OK) vResult = true;
else if (response.StatusCode == HttpStatusCode.NotFound) vResult = false;
else vResult = vResErrorDefault;
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
{
var resp01 = (HttpWebResponse)ex.Response;
if (resp01.StatusCode == HttpStatusCode.NotFound)
{
vResult = false;
}
else
{
vResult = vResErrorDefault;
}
}
else
{
vResult = vResErrorDefault;
}
}
finally
{
// Don't forget to close your response.
if (response != null)
{
response.Close();
}
}
return vResult;
}
Anoter version with define timeout :
public bool URLExists(string url,int timeout = 5000)
{
...
webRequest.Timeout = timeout; // miliseconds
...
}
This works for me:
bool HaveFile(string url)
{
try
{
using (WebClient webClient = new WebClient())
{
webClient.DownloadString(url);
}
return true;
}
catch (Exception)
{
return false;
}
}