Web API Requests happening enormous times - c#

I am calling WEB API call using the following code in web service(.asmx).
Server.ScriptTimeout = 3600;
return util.util.Settle(ids, userName, userPwd, userBelongCountry);
Settle method invokes MakeRequest() as given below:
public Dictionary<string, string> MakeRequest(string addressAPI)
{
HttpWebRequest r=null;
try
{
r = (HttpWebRequest)WebRequest.Create(addressAPI);
r.Method = "Get";
HttpWebResponse res = (HttpWebResponse)r.GetResponse();
Stream sr = res.GetResponseStream();
StreamReader sre = new StreamReader(sr);
var s = sre.ReadToEnd();
sre.Close();
XDocument doc = XDocument.Parse(s);
foreach (XElement element in doc.Descendants().Where(p => p.HasElements == false))
{
int keyInt = 0;
string keyName = element.Name.LocalName;
while (!this.dataDictionary.ContainsKey(keyName))
{
keyName = element.Name.LocalName + "_" + keyInt++;
this.dataDictionary.Add(keyName, element.Value);
}
}
return this.dataDictionary;
}
catch (Exception ex)
{
SystemLogWebCom.Error("Error in WEBAPI call" + ex.ToString());
return null;
throw ex;
}
}
Problem:If any exception occurred the WEB API is getting called enormous times approx.15000+ times continuously. It supposed to execute once and return back.
Error logged in Logger:
"Error in WEBAPI callSystem.ArgumentException: An item with the same key has already been added.at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at WebAPICommunicator.Utility.MakeRequest(String addressAPI)".
I am wondering how come these many number of times it is invoking and the same number of errors i could see in Logger.
Now I have included
finally
{
r.Abort();
}
Can it solve the problem?

First is that you don't dispose streams in a finally block.
And second that your exception will never be re thrown because nothing will be executed after "return null" in catch, "throw ex;" is dead code.
Your exception is been thrown because of you using while instead of if:
while (!this.dataDictionary.ContainsKey(keyName))
if (!this.dataDictionary.ContainsKey(keyName))
Dictionaries can not contain duplicate keys, and that's what is happening here the second time you read the same key from xml.

Related

One or more errors occurred. (Exception of type 'System.OutOfMemoryException' was thrown.)

I'm running into below mentioned error when a list of more than 30k items is created, via Lambda function.
Error:
System.Collections.Generic.List`1.set_Capacity(Int32 value) at System.Collections.Generic.List`1.EnsureCapacity(Int32 min) at System.Collections.Generic.List`1.AddWithResize(T item) at
at System.Collections.Generic.List`1.set_Capacity(Int32 value)
at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
at System.Collections.Generic.List`1.AddWithResize(T item)
at AWSLambda3.Function.ListS3ObjectsAsync(String bucketName, String filestoDwnld, IAmazonS3 client)
Code:
public async Task<List<string>> ListS3ObjectsAsync(string bucketName, string filestoDwnld, IAmazonS3 client)
{
//int fileCount = 0;
List<string> pdfFiles = new List<string>();
ListObjectsRequest request = new ListObjectsRequest
{
BucketName = bucketName,
Prefix = filestoDwnld,
};
ListObjectsResponse response = await client.ListObjectsAsync(request);
do
{
foreach (S3Object entry in response.S3Objects)
pdfFiles.Add(entry.Key);
if (response.IsTruncated)
{
request.Marker = response.NextMarker;
}
else
request = null;
} while (request != null);
return pdfFiles;
}
I've also tried increasing list capacity, but that doesn't help as well. Please assist.
The reason for the OutOfMemoryException is in the infinite loop that is triggered when response.IsTruncated == true In this case the request is never set to null and the loop doesn't stop. The code restart a new loop loading again the same set of elements into the list pdfFiles and so on until you have no more memory.
I don't know exactly how your service backend works but I could immagine that you need to change just one line of code inserting the request to the service call inside the loop
do
{
// This inside the loop will be executed at least one time and
// eventually again until the IsTruncated property is set to true.
ListObjectsResponse response = await client.ListObjectsAsync(request);
foreach (S3Object entry in response.S3Objects)
pdfFiles.Add(entry.Key);
if (response.IsTruncated)
{
request.Marker = response.NextMarker;
}
else
request = null;
} while (request != null);
In this way, after the first loop you ask again a new set of elements from the service backend pointing at the NextMarker and eventually you will reach a point in which IsTruncated will be false ending the loop

AggregateException "One or more errors occurred.An error occurred while sending the request."

I tried to post a file to an API rest from my WCF .Net framework 4.5. Here is my code:
public string CreateConclusion(string[] instanceUIDs)
{
var root = #"C:\";
string filename = "1.2.840.114257.1.9.1245.56421.52314.1119854.01248.dcm";
using (var client = new HttpClient())
{
var stream = new FileStream(root + filename, FileMode.Open);
using (var content =
new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)))
{
content.Add(new StreamContent(stream), "fileToUpload", filename);
using (var message = client.PostAsync("https://localhost:44343/api/ConclusionReports/UploadFile", content).Result)
{
var input = message.Content.ReadAsStringAsync();
return !string.IsNullOrWhiteSpace(input.Result) ? Regex.Match(input.Result, #"http://\w*\.directupload\.net/images/\d*/\w*\.[a-z]{3}").Value : null;
}
}
}
}
It doesn't work and throw an exception: "One or more errors occurred.An error occurred while sending the request."
Does anyone can help me to solve this problem? Thank you in advance
An aggregate exception can always be unwrapped to discover the real cause. Try to write your client call inside a try-catch like this:
try {
//Some risky client call that will call parallell code / async /TPL or in some way cause an AggregateException
}
catch (AggregateException err){
foreach (var errInner in err.InnerExceptions) {
Debug.WriteLine(errInner); //this will call ToString() on the inner execption and get you message, stacktrace and you could perhaps drill down further into the inner exception of it if necessary
}
}

C# - StreamReader ReadToEnd - WebException: The request was aborted: The request was canceled

My app produces the following error randomly. I havent been able to re-produce it on my machine, but on users who have installed it, it happens to them.
System.Net.WebException: The request was aborted: The request was canceled.
at System.Net.ConnectStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadToEnd()
Whats odd is, ReadToEnd() cant product a WebException error (Found out by hovering over it and seeing what type of exceptions it can cause), yet from this Crash Dump it is?, To make sure I even put a WebException try catch and it still happens.
I read online a tiny bit and see it might be caused by ServicePointManager.DefaultConnectionLimit so I added that in with 1000 int value, and now im not sure if it fixed it - I havent seen any reports, but that doesnt mean its not happening.
using (HttpWebResponse resp = (HttpWebResponse)r.GetResponse())
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string s = "";
try { s = sr.ReadToEnd(); }
catch (IOException) { return "2"; }
catch (WebException) { return "2"; }
}
This is the code im using, if needed, I can provide r's values. Just know that I use quite a lot.
EDIT: I can confirm on the client's side that even with the ServicePointManager.DefaultConnectionLimit set to 1000 it still occurs.
I had a similar problem to this some time ago. Can you handle the WexException doing something like this:
public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
try
{
return (HttpWebResponse) request.GetResponse();
}
catch (WebException ex)
{
if(ex.Response == null || ex.Status != WebExceptionStatus.ProtocolError)
throw;
return (HttpWebResponse)ex.Response;
}
}
I borrowed the code above from the answerer here: HttpWebRequest.GetResponse throws WebException on HTTP 304
Then the first line of your code would do this:
using (HttpWebResponse resp = GetHttpResponse(r))
Found out what managed to fix it, no idea WHY, but this works:
try
{
using (HttpWebResponse resp = httpparse.response(r))
{
if(resp != null)
{
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string s = "";
try { s = sr.ReadToEnd(); }
catch (IOException) { return "2"; }
}
} else
{
return "2";
}
}
}
catch (WebException)
{
return "2";
}
Makes no sense, the error occurs at sr.ReadToEnd(), yet putting the Try Catch over the response() makes it fixed?

Catching exception (and ignoring) in called method, but need to throw it in caller

I have a method that tries to get a web page. I want to attempt to get it several times so I built a wrapper around it to retry several times. In the method called I catch and then ignore the exception returning null. Therefore, after the first attempt the retries will occur. Here is the called method:
internal static async Task<string> WebClientAsync(string URI, NetworkCredential Creds = null, Dictionary.FantasySite Site = Dictionary.FantasySite.Other)
{
if (Creds == null)
{
try
{ //attempt to get the web page
HttpClient client = new HttpClient(); //create client
HttpResponseMessage response = await client.GetAsync(URI); //get response
response.EnsureSuccessStatusCode(); //ensure the response is good (or throw Exception)
return await response.Content.ReadAsStringAsync(); //return the string back
}
catch (HttpRequestException)
{
//MessageBox.Show(string.Format("\nHttpRequestException Caught!\nMessage :{0} for URI {1}.", e.Message, URI));
return null; //Catch the exception because we wrapped this and are trying again (null is the indicator it didn't work)
}
catch (Exception)
{
//MessageBox.Show(string.Format("\nException Caught!\nMessage :{0} for URI {1}.", e.Message, URI)); //TODO - THis hasn't happened, but remove it for production
return null; //Catch the exception because we wrapped this and are trying again (null is the indicator it didn't work)
}
}
}
If this still fails after all the retries then I want to throw the exception, but since I threw it away, I can't. Here is the calling method.
internal static async Task<string> WebClientRetryAsync(string URI, NetworkCredential Creds = null, Dictionary.FantasySite Site = Dictionary.FantasySite.Other)
{
string webPage = null;
for (int i = 0; i < Dictionary.WEB_PAGE_ATTEMPTS; i++) //Attempt to get the webpage x times
{
System.Diagnostics.Debug.Print(string.Format("WebClientRetryAsync attempt {0} for {1}", i + 1, URI));
//wait some time before retrying just in case we are too busy
//Start wait at 0 for first time and multiply with each successive failure to slow down process by multiplying by i squared
Thread.Sleep(Wait.Next(i * i * Dictionary.RETRY_WAIT_MS));
webPage = await WebClientAsync(URI, Creds, Site);
if (webPage != null) { break; } //don't attempt again if success
}
/*TODO - If webPage is null we didn't have success and need to throw an exception.
* This is done in the calls to this method and should be done here, move code over */
return webPage;
}
Can someone suggest if this is a bad approach and how I could refactor the code to throw the exception after failing too many times? Should I pass the exception to the calling method and ignore it until the retries have run out?
Yup. You should not throw away exceptions that you wish to rethrow. One possible approach is the following (trying to make a minimal amount of modifications to your current code):
internal static async Task<string> WebClientAsync(string URI, NetworkCredential Creds = null, Dictionary.FantasySite Site = Dictionary.FantasySite.Other)
{
// If (Creds == null) removed, you must return a task or throw an exception.
//attempt to get the web page
HttpClient client = new HttpClient(); //create client
HttpResponseMessage response = await client.GetAsync(URI); //get response
response.EnsureSuccessStatusCode(); //ensure the response is good (or throw Exception)
return await response.Content.ReadAsStringAsync(); //return the string back
}
internal static async Task<string> WebClientRetryAsync(string URI, NetworkCredential Creds = null, Dictionary.FantasySite Site = Dictionary.FantasySite.Other)
{
// assumes you have .NET 4.5, otherwise save exception.
// uses System.Runtime.ExceptionServices;
ExceptionDispatchInfo exceptionDispatchInfo = null;
for (int i = 0; i < Dictionary.WEB_PAGE_ATTEMPTS; i++) //Attempt to get the webpage x times
{
System.Diagnostics.Debug.Print(string.Format("WebClientRetryAsync attempt {0} for {1}", i + 1, URI));
try
{
var webPage = await WebClientAsync(URI, Creds, Site);
return webPage;
}
catch (Exception ex)
{
// save exception so it can be rethrown.
exceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);
}
// Edit: also need to do an async wait (no thread.sleep):
if (i < Dictionary.WEB_PAGE_ATTEMPTS - 1)
{
//wait some time before retrying just in case we are too busy
//Start wait at 0 for first time and multiply with each successive failure to slow down process by multiplying by i squared
await Task.Delay(Wait.Next(i * i * Dictionary.RETRY_WAIT_MS));
}
}
Debug.Assert(exceptionDispatchInfo != null); // shouldn't be null if we get here.
exceptionDispatchInfo.Throw();
}

c# application is crashing when the server is down

I'm using this code, to fetch the latest version of my app in *Form1_Load*:
string result1 = null;
string url1 = "http://site.com/version.html";
WebResponse response1 = null;
StreamReader reader1 = null;
try
{
HttpWebRequest request1 = (HttpWebRequest)WebRequest.Create(url1);
request1.Method = "GET";
response1 = request1.GetResponse();
reader1 = new StreamReader(response1.GetResponseStream(), Encoding.UTF8);
result1 = reader1.ReadToEnd();
}
catch (Exception ex)
{
// show the error if any.
}
finally
{
if (reader1 != null)
reader1.Close();
if (response1 != null)
response1.Close();
}
The problem is that when I shut the server down the whole application is stucking and a window is popping out,saying:
Unable to connect to the remote server
Which seems legit.
Is there a way to bypass this crash (when the server is down) and break out of the version checking?
Add an additional catch block that catches the specific Exception type that you're seeing... the code will look like...
try
{
//*yadda yadda yadda*
}
catch (System.Net.WebException WebEx)
{
//*Correctly set up a situation where the rest of your program will know there was a connection problem to the website.*
}
catch (Exception ex)
{
//*Do the error catching you do now*
}
finally
{
//*yadda yadda*
}
This construction will allow you to handle WebExceptions differently from other kinds of exceptions: note that all Exceptions derive from one base class, Exception, and you can make your own for uses like this.

Categories

Resources