views:

160

answers:

4

My web service program is supposed to generate a random code and return it to the client program. Right now it returns "" as the code instead of the randomly generated code. What is wrong with my variable scopes? Thanks.

public class Service1 : System.Web.Services.WebService
{
    private string code = "";

    [WebMethod]
    public void StartGame()
    {
        // Pick a secret code
        // R, B, G, O, T, W, P, Y
        Random random = new Random();
        for (int i = 0; i < 4; i++)
        {
            int num = random.Next(8) + 1;
            if (num == 1)
                this.code += "R";
            else if (num == 2)
                this.code += "B";
            else if (num == 3)
                this.code += "G";
            else if (num == 4)
                this.code += "O";
            else if (num == 5)
                this.code += "T";
            else if (num == 6)
                this.code += "W";
            else if (num == 7)
                code += "P";
            else if (num == 8)
                this.code += "Y";
        }
    }

    [WebMethod]
    public string MakeGuess(string guess)
    {
        return this.code;
    }
}
+12  A: 

The problem is those methods get called on two separate instances of the class. Each method is invoked once on a new instance of the class as an HTTP request comes in and the class will be thrown away. The server will have no idea that those requests are related in some way due to the stateless nature of HTTP protocol.

Mehrdad Afshari
I believe I understand what you are saying. Like jmayor advised, I should use sessions. I am also going to ask you if you know of any good references on sessions. Thank you!
Louise
Lou: Look it up on MSDN. Also, you could manage the state yourself by requiring the clients to pass an ID when they call the methods (and provide a method to issue client IDs).
Mehrdad Afshari
+1  A: 

Are you making two different calls , one to invoke the start game and another to call the MakeGuess? separate calls would imply creation of different objects on the server side. You should create sessions or make the code var static.

jmayor
Hi, making the variable 'code' static worked. Can you explain why though so I can better understand? Also, how would I go about making a session? If you could point me to some reference I would appreciate it! Thanks
Louise
You are using code as a variable to your class. It means it will live as long as the instance of your class lives. When you are invoking a WebMethod on the server side and instance of your class is created to execute your method. You are using the method 'StartGame' and your 'code' variable get your desired result, but when the method execution ends your object is destroyed. Calling the second method creates a new instance to execute your MakeGuess, now 'code' var is is empty because is new. By making this code static it lives whether different instances of your class are created
jmayor
Static solves your issue here but is not the more elegant, if you call your WebService twice you'll see that code will have both results one after another, you need to reset it each time you startGame gets called. Consider using a local variable and a single function call( as some other solutions here suggests) or you can look over on ASP.NET bibliography and get familiar with Sessions, just by googling implementing Session on .Net Web Services will bring some interesing articles to read.
jmayor
A: 

If there is no specific need for two calls why not making a simple method?

`

[WebMethod]
    public string MakeGuess(string guess)
    {
        private string code = "";
        // Pick a secret code
        // R, B, G, O, T, W, P, Y
        Random random = new Random();
        for (int i = 0; i < 4; i++)
        {
            int num = random.Next(8) + 1;
            if (num == 1)
                this.code += "R";
            else if (num == 2)
                this.code += "B";
            else if (num == 3)
                this.code += "G";
            else if (num == 4)
                this.code += "O";
            else if (num == 5)
                this.code += "T";
            else if (num == 6)
                this.code += "W";
            else if (num == 7)
                code += "P";
            else if (num == 8)
                this.code += "Y";
        }
        return code;
    }
Thanks for the help, but I would rather keep my methods broken down into smaller steps because I plan on adding more steps later. :)
Louise
+1  A: 

Presented without additional comment:

public static string GenerateRandomCode(int length)
{
    const string charset = "RBGOTWPY";

    string randomCode = "";
    Random random = new Random();

    while (length > 0)
    {
        length--;
        randomCode += charset[random.Next(charset.Length)];
    }
    return randomCode;
}
Wedge
Thank you. I'm saying "duh" to myself.
Louise