Best way to handle this HttpWebRequest in a For loop? - c#

Question Background:
I am making a call to Amazon's Product Advertising API. This gives back X number of paged results at a time with an node in the XML stating how many pages are available i.e 10. A page number is then specified and the API will responsed with the results for that given page.
Question:
I want to add all of the results from each page to a list that I then send to an MVC view. Currently I'm doing this through a For Loop specifying the upper limit as the maximum number of loops, for example if there are 10 pages available I'm looping round page 1, 2, 3, 4......and so on until 10.
The following code shows how the request is currently being made. Is this ok? It works but I have seen a StackOverflow exception a couple of times when debugging.
for (int i = 1; i <= 10; i++)
{
string requestUrl = "http://amazonApi.com/page"+i;
WebRequest amazonRequest = HttpWebRequest.Create(requestUrl);
try
{
WebResponse response = amazonRequest .GetResponse();
XmlDocument doc = new XmlDocument();
doc.Load(response.GetResponseStream());
XmlDocument xmlDoc = doc;
//Add Xml Document to List.....
AddToList(xmlDoc);
}
catch (Exception e)
{
System.Console.WriteLine("Caught Exception: " + e.Message);
System.Console.WriteLine("Stack Trace: " + e.StackTrace);
}
}

Related

Google Geocode null reference exception

I have made a program that takes the longitude and latitude from several properties on a london property portal.
What I am to do next is send those long+lat to geocode and return the full formatted address. The below code works for a majority of URLs that I have in my geocodeURL list, but occasionally it returns a null reference exception.
When I check the URL that failed and returned the exception manually in a browser, it works fine.
If that is the case, what am I doing wrong?
for (int i = 0; i < longitude.Count; i++)
{
Console.WriteLine(longitude[i]);
Console.WriteLine(latitude[i]);
//Console.WriteLine("http://maps.google.com/maps/api/geocode/xml?latlng=" + latitude[i] + "," + longitude[i] + "&sensor=false");
geocodeURL.Add("https://maps.googleapis.com/maps/api/geocode/xml?latlng=" + latitude[i] + "," + longitude[i] + "&key=0000");
}
foreach (string i in geocodeURL)
{
try
{
var requestUri = string.Format(i);
var request = WebRequest.Create(requestUri);
var response = request.GetResponse();
var xdoc = XDocument.Load(response.GetResponseStream());
var result = xdoc.Element("GeocodeResponse").Element("result");
var fullAddy = result.Element("formatted_address").Value;
address.Add(fullAddy);
Console.WriteLine(fullAddy);
}
catch (Exception e)
{
Console.WriteLine(i);
Console.WriteLine(e);
}
}
The XMl response looks like this:
<GeocodeResponse>
<status>OK</status>
<result>
<type>street_address</type>
<formatted_address>4 Sydenham Ave, London SE26 6UH, UK</formatted_address>
One such example of the exception, and you can see the URL seems to be fine, but it throws an exception regardless... (I have blacked out the key fyi)
Google have a limit on how many results you can send in a certain amount of time. Since you are sending hundreds of requests at a time, you are probably running up against this limit and the error is google's way of telling you to either cough up some cash or gtfo.
If you don't want to pay up, you could put a Thread.Sleep(2000) (or some other wait period) every few requests to get around the limit.

C# How to get method and selector from NoSuchElementException

I'm using C#.NET 4 and Selenium WebDriver 2.44.0.0 and chromeDriver.
When it cannot find element, Selenium throws error:
no such element
(Session info: chrome=38.0.2125.104)
(Driver info: chromedriver=2.10.267521,platform=Windows NT 6.1 SP1 x86_64)
But I would like to know which element is missing. I see some articles said that it can show details like this:
OpenQA.Selenium.NoSuchElementException: Unable to locate element: {"method":"id","selector":"hello"}
Could anyone tell me how to get the method and selector from NoSuchElementException?
Here is my code
try
{
for(int i=0; i<10; i++)
{
string className = "items-" + i;
IWebElement t = Driver.FindElement(By.CssSelector("[class$='" + className + "'] > span"));
t.Click();
}
}
catch (NoSuchElementException ex)
{
Logger.Error("Error: " + ex.Message);
Debug.WriteLine(ex.Message);
}
The .ToString() method of the By locator returns what you're asking for.
As far as I know the exception itself does not contain the information. However, it is straight forward to handle the exception and associate it with the locator function that was used in the FindElement() method that threw it.
For example, if the element in the 5th iteration cannot be found, the code below will produce this message
Error: no such element
Error: Unable to find element using function By.CssSelector: [class$='items-4'] > span
By locator; // need to declare this outside the scope of the try block
// so it can be accessed in the catch block
try
{
for(int i=0; i<10; i++)
{
string className = "items-" + i;
locatorFunction = By.CssSelector("[class$='" + className + "'] > span")
IWebElement t = Driver.FindElement(locatorFunction);
t.Click();
}
}
catch (NoSuchElementException ex)
{
Logger.Error("Error: " + ex.Message);
Logger.Error("Error: Unable to find element using function " + locatorFunction.ToString());
}
Refer to selenium API doc for .net found here.
But, I don't think it will give you what you want in terms of exception tracking. Print the selector you are using instead which can help you identify the element throwing the error

StackOverflowException was unhandled when trying to count how many pages are in a PDF

I have an application that runs from a batch file using parameters in said file to pull PDF email attachments from an email inbox. It takes those and saves them onto drive so our web app can display them to a user. Essentially it is an incoming email handler.
Anyway, I am getting this error:
System.StackOverflowException was unhandled
{Cannot evaluate expression because the current thread is in a stack
overflow state.}
Here is the code:
static List<string> SplitPDF(string PDFPath)
{
try
{
List<string> retval = new List<string>();
ExpertPdf.PDFSplit.PDFSplitManager pds = new PDFSplitManager();
pds.LicenseKey = "XXXXXXXXXXXX";
int Pages = pds.GetPdfPageCount(PDFPath);
for (int i = 0; i < Pages; i++)
{
pds.ExtractPagesFromFileToFile(PDFPath, PDFPath + i.ToString() + ".pdf", i + 1, 1);
retval.Add(PDFPath + i.ToString() + ".pdf");
}
retval.Add(PDFPath);
return retval;
}
catch (Exception ex)
{
throw ex;
}
}
This method throws the error on
int Pages = pds.GetPdfPageCount(PDFPath);
Don't know why or how. The funny thing is, it only happens with one of three batch files. The other two work fine (Production fails, dev and test work fine).
We think it may have to do with the file folders, maybe something is happening in there, but I am unsure...
Any suggestions? Need any other code? I know I only provided one method, but that is where the error is.
Thanks!
EDIT: here is the stack trace, if it helps
IncomingFax.exe!IncomingFax.Program.SplitPDF(string PDFPath = "D:\www\443\PBIN\fax\inbox\preproc\3lz3npbd2sy") Line 726 + 0x17 bytes
IncomingFax.exe!IncomingFax.Program.ProcessMessage(ForAspNet.POP3.EmailMessage Message = {ForAspNet.POP3.EmailMessage}) Line 326 + 0x9 bytes
IncomingFax.exe!IncomingFax.Program.Main(string[] args = {string[6]}) Line 78 + 0x9 bytes

Using webdriver PageFactory to pick certain page

I have a web project where clicking a button navigates to another page. The new page can be 1 of three possible pages depending on data in the server. (The url may be the same for 2 of those pages)
I have three classes representing expected elements on each page using the PageObject model.
What is the best way to actually find what page actually got loaded? Is there an OR type of wait that I can wait on three unique elements and get the one that actually got loaded?
Yes, it is possible to check the presence of unique element (which identifies the page) and then return respective page in the framework.
However, a test should know the page it is expecting next and should assume that the correct page has loaded and perform further actions/assertions. You can even put an assertion here to verify correct page has loaded. If a different page has loaded, then the test eventually fails as assertions would fail.
This way test becomes more readable and describes flow of application.
Also, setting up test data upfront for the tests, is always advisable. This way you would know what data is available on server and test would know which page would render.
I had a similar issue where I needed to detect if a login was for a new user (the login page then goes to a terms & conditions page rather than direct to the home page).
Initially I just waited and then tested the second page but this was just a pain so I came up with this.
To Test the result with this:
var whichScreen = waitForEitherElementText(By.CssSelector(HeaderCssUsing), "HOME SCREEN", "home", terms.getHeaderLocator(), terms.headerText, "terms", driver, MAX_STALE_RETRIES);
if(whichScreen.Item1 && whichScreen.Item2 == "terms")
{
terms.aggreeToTerms();
}
The method that this calls is :
protected Tuple<bool, string> waitForEitherElementText(By locator1, string expectedText1, string return1Ident,
By locator2, string expectedText2, string return2Ident, IWebDriver driver, int retries)
{
var retryCount = 0;
string returnText = "";
WebDriverWait explicitWait = new WebDriverWait(driver, TimeSpan.FromSeconds(globalWaitTime));
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0.5));
while (retryCount < retries)
{
try
{
explicitWait.Until<bool>((d) =>
{
try
{
if (Equals(d.FindElement(locator1).Text, expectedText1)) { returnText = return1Ident; };
}
catch (NoSuchElementException)
{
if (Equals(d.FindElement(locator2).Text, expectedText2)) { returnText = return2Ident; };
}
return (returnText != "");
});
return Tuple.Create(true, returnText);
}
catch (StaleElementReferenceException e)
{
Console.Out.WriteLine(DateTime.UtcNow.ToLocalTime().ToString() +
":>>> -" + locator1.ToString() + " OR " + locator2.ToString() + "- <<< - " +
this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name +
" : " + e.Message);
retryCount++;
}
}
return Tuple.Create(false,"");
}
The explicit wait until uses a boolean so will loop around for the full wait time (I have a very slow Test server so I set this to 60 seconds). the implicit wait is set to half a second so the element tests will attempt every half a second and loop around until either true is returned or it fails.
I use a Tuple so that I can detect which screen I am on, and in this case agree to the terms & conditions which then sets me back on my normal page path

Domain checker (Whois)?

to all.
i developing a webpage using asp.net with c# language, in this webpage i have a textbox for taking url of the domain and button. when user enter domain name in the textbox and press the button the details of the domain will displaying in the other window. i take help from stackoverflow user and i get the code it is working fine, but when i type the domain name particularly ".in" doamins are not giving details. simply domain available message is displaying actually the domain is registered for example i tried "axisbank.co.in" in my page it is displaying the domain is available but actually it is already taken. I am sending my code please help me ( particularly .in domain names)
protected void Button1_Click(object sender, EventArgs e)
{
lblDomainName.Text = Session["WhoIs"].ToString();
string firstLevelbufData = null;
// Stores the bufData extracted from the webclient
try
{
// similarly we can select any server address for bufData mining
string strURL = "http://www.directnic.com/whois/index.php?query=" + txtDomain.Text;
WebClient web = new WebClient();
// byte array to store the extracted bufData by webclient
byte[] bufData = null;
bufData = web.DownloadData(strURL);
// got the bufData now convert it into string form
firstLevelbufData = Encoding.Default.GetString(bufData);
}
catch (System.Net.WebException ex)
{
// this exception will be fired when the host name is not resolved or any other connection problem
//txtResult.Text = ex.Message.ToString();//sasi
lblresult.Text = ex.Message.ToString();
return;
}
try
{
// first and last are the regular expression string for extraction bufData witnin two tags
// you can change according to your requirement
string first = null;
string last = null;
// chr(34) is used for (") symbol
first = "<p class=\"text12\">";
last = "</p>";
Regex RE = new Regex(first + "(?<MYDATA>.*?(?=" + last + "))", RegexOptions.IgnoreCase | RegexOptions.Singleline);
// try to extract the bufData within the first and last tag
Match m = RE.Match(firstLevelbufData);
// got the result
//txtResult.Text = m.Groups["MYDATA"].Value + "<br>";//sasi
lblresult.Text = m.Groups["MYDATA"].Value + "<br>";
// check if no information abour that domain is available
//if (txtResult.Text.Length < 10) txtResult.Text = "Domain "+ txtDomain .Text +" is Available";//sasi
if (lblresult.Text.Length < 10)
lblresult.Text = "Domain " + txtDomain.Text + " is Available";
}
catch (System.Net.WebException ex)
{
lblresult.Text = " Sorry the information is currently not available !! ";
}
}
help me thank you
http://www.directnic.com
does not have information about .co.in domain names.
Most of the whois sites won't allow you to fetch the results before filling in CAPTCHA.
http://registry.in/ is the official registry, try using whois protocol at whois.registry.in

Categories

Resources