Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Can I recursively call a method from inside that method?

Posted on 2011-09-28
4
Medium Priority
?
209 Views
Last Modified: 2013-12-17
I have a method that calls an API which may or may not return with valid data.  If the data is not valid, I need to change a parameter and call the API again (see line 123).  This second time, if the data is not found, then I want to set a flag and return to the original caller.  Is there anything special I need to do (like where is the "return" statement  going to take me?)
public string imageURL = "";
        //------------------------------    look for book and parse results    ---------------------------|
        private bool InvokeItemSearch(string asin, string AWSKey, string AWSSecretKey) {
            Cursor.Current = Cursors.WaitCursor;

            string idType = asin.Substring(0, 1) == "B" ? idType = "ASIN" : idType = "ISBN";
            string associateTag = "abcdef-10"; //"pragbook-20";
            string requestString =
                "Service=AWSECommerceService" +
                "&Version=2011-08-01" +
                "&Operation=ItemLookup" + 
                "&ItemId=" + asin +
                "&IdType=" + idType +
                "&MerchantId=All" +
                "&AssociateTag=" + associateTag +
                "&ResponseGroup=Medium";

            if (idType == "ISBN")
                requestString += "&SearchIndex=Books";

            SignedRequestHelper helper = new SignedRequestHelper(AWSKey, AWSSecretKey, @"ecs.amazonaws.com");
            string requestURL = helper.Sign(requestString);
            WebRequest request = HttpWebRequest.Create(requestURL);


            request.Timeout = 30000;  //  30 seconds
            System.Net.ServicePointManager.MaxServicePointIdleTime = 10000;  //  needed for bug in .NET 2.0

            // get the response object
            HttpWebResponse response = null;
            try {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (Exception ex) {
                if (ex.Message.Contains("(403) Forbidden")) {
                    MessageBox.Show("Invalid Amazon key(s); verify them and try again", "Prager, Software", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
            }
            imageURL = "";  //  clear it...

            // to read the contents of the file, get the ResponseStream
            StreamReader sr = null;
            try {
                sr = new StreamReader(response.GetResponseStream());
            }
            catch (Exception ex) {
                if (ex.Message.Contains("unable to connect to the remote server")) {
                    MessageBox.Show("Amazon.com appears to be busy; please try again", "Prager, Software", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }
            }


            // Create an insntance of XmlTextReader and call Read method to read the file
            XmlTextReader textReader = new XmlTextReader(sr);
            textReader.Read();


            bool notFound = true;
            //string debugString = textReader.
            try {
                textReader.MoveToAttribute("ItemAttributes");
            }
            catch (Exception ex) {
                if (ex.Message.Contains("Root element is missing")) {
                    MessageBox.Show("Data returned from Amazon.com is invalid - try again", "Prager, Software", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    textReader.Close();  //  close the text reader
                    return false;
                }
            }

            while (textReader.Read()) {
                if (textReader.NodeType == XmlNodeType.Element && textReader.NodeType != XmlNodeType.EndElement)
                    switch (textReader.LocalName) {
                        case "Author":
                            textReader.Read();  //  get value
                            tbAuthor.Text = textReader.Value.Length > 75 ? textReader.Value.Substring(0, 75) : textReader.Value;
                            notFound = false;
                            break;
                        case "Binding":
                            textReader.Read();  //  get value
                            coBinding.Text = textReader.Value;
                            if (coBinding.Text.ToLower().Contains("paperback"))
                                coJacket.SelectedIndex = 8;  // none as issued 
                            notFound = false;
                            break;
                        case "NumberOfPages":
                            textReader.Read();  //  get value
                            tbPages.Text = textReader.Value.ToString();
                            notFound = false;
                            break;
                        case "PublicationDate":
                            textReader.Read();  //  get value
                            string[] splitFields = textReader.Value.Split('-');
                            tbYear.Text = splitFields[0];  //  just take the year
                            notFound = false;
                            break;
                        case "Publisher":
                            textReader.Read();  //  get value
                            tbPub.Text = textReader.Value.Length > 85 ? textReader.Value.Substring(0, 85) : textReader.Value;
                            notFound = false;
                            break;
                        case "Title":
                            textReader.Read();  //  get value
                            tbTitle.Text = textReader.Value.Length > 100 ? textReader.Value.Substring(0, 100) : textReader.Value;
                            notFound = false;
                            break;
                        case "Content":
                            textReader.Read();  //  get value  (11.4.0)
                            if (cbAddDesc.Checked)
                                tbDesc.Text = textReader.Value.Length > 500 ? textReader.Value.Substring(0, 500) : textReader.Value;
                            else
                                tbDesc.Text = "";
                            notFound = false;
                            break;
                        default:
                            break;
                    }
            }

            if (notFound) {  //  if we didn't find anything using ISBN, try again using ASIN
			//  this is where I want to set a flag at the top of the method and call InvokeItemSearch again   <------------------------
                return false;
            }

Open in new window

0
Comment
Question by:rmmarsh
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 2000 total points
ID: 36720167
You have to understand how function calls work in your machine. Such calls go onto a stack. Think of a stack of plates. Start with one plate. Now add a second. Can you remove the bottom plate without removing the top plate? That's how your function calls work. When you recursively call your function, a new copy is placed on the stack, and its parameters and values are seen only by it (barring any global variables).

Let's say you are in the first call (bottom plate). You get to line 123. Now you call the function a second time (top plate). The second call has to complete before the first call can be removed from memory. This is where you will be if you call the function a second time. Once the second call completes, you will be at line 124 of the first call. Just be sure to be careful if there are any global variables because you can affect the values of other calls by mutating them in any given call, just like normal execution (i.e. non-recursive) can.
0
 

Author Comment

by:rmmarsh
ID: 36720219
Hmmm... I think it would be safer to take the guts of the method and make another method out of it which could be called again (without recursion) depending on the results of the first call...

You agree?
0
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 2000 total points
ID: 36720351
It's probably more a matter of preference. You can certainly do that, but it is two pieces of code you have to maintain--if one changes, the other will most likely have to be changed (and you have to remember that the other needs to be changed!).

Recursion is not difficult to mess up (e.g. infinite recursion, incorrect values due to globals, etc.), but it's not terribly difficult to grasp if you practice it for a bit. Perhaps if you clarify your worries we can cover possible points of error or provide a better explanation.
0
 

Author Closing Comment

by:rmmarsh
ID: 36720461
Thank you... I appreciate it...
0

Featured Post

Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question