Can I recursively call a method from inside that method?

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

rmmarshAsked:
Who is Participating?
 
käµfm³d 👽Connect With a Mentor Commented:
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
 
käµfm³d 👽Connect With a Mentor Commented:
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
 
rmmarshAuthor Commented:
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
 
rmmarshAuthor Commented:
Thank you... I appreciate it...
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.