Solved

Can I recursively call a method from inside that method?

Posted on 2011-09-28
4
203 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
  • 2
  • 2
4 Comments
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 total points
Comment Utility
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
Comment Utility
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 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
Comment Utility
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
Comment Utility
Thank you... I appreciate it...
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Flash (http://en.wikipedia.org/wiki/Adobe_Flash) has evolved over the years to where it has become a masterful tool for displaying content screen.  It has excellent layout placement, UI precision as well as rendering capabilities. This, along with t…
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…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

762 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now