How to change ViewState value in a for loop?

99 Views Asked by At

I have a for loop and want too change value of ViewState everytime if statement is true and want it to show it in real time:

int load; int count;

protected void Button1_Click(object sender, EventArgs e)
        {


        for (int time = 0; time < 900000; time++)
        {
              count =+1;



            if (ViewState["load"] == null)
            {

              
                load = 0;


            }

            else
            {

                if (count == 50)
                {

                    load = (int)ViewState["load"] + 100;

                }

                else if (count == 500000)
                {


                   load = (int)ViewState["load"] + 200;

                }

                else if (count == 800000)
                {

                    load = (int)ViewState["load"] + 111;

                }



                ViewState["load"] = load;
                Label1.Text = load.ToString();
            }
        }
    }

it only shows the last value but I want it to show all values everytime the statment is true ...

1

There are 1 best solutions below

1
On

Changing viewstate, or even just a simple text box does NOT make any difference here. You can not use or "leverage" viewstate unless you allow and have a full page life cycle. However, using view state is NOT ANY different then code behind setting a text box! You set a text box or viewstate, the user will NOT see that change unless the page is allowed to travel back to the client.

You have to learn how a web page works.

Code behind does not modify the web page sitting on the users desktop. Changes are only seen after the so called "round trip" is completed.

So, code behind never interacts with the end user, and changes made by code behind are never seen until such time the WHOLE web page makes the trip back to the client side.

So, we have this:

enter image description here

Note close, the web page is sitting on the users desktop. The server does NOT have a copy of the web page in memory. In fact, the server is waiting for ANY user (not just you!) to post a page to the web server. On post to the server, then the server process that one page. The web server is ONLY one computer, and you can think of that web server like one desktop computer!

So, when you click a button, then the WHOLE web page is sent up to the server.

When you post-back, THEN and ONLY then is a instance of your page class created in memory on the server side. Your code behind then runs, page is rendered, sent back to client and then the page is disposed - removed from memory. Web server is now waiting for the next post-back.

So, you have this:

enter image description here

So, you click on a button. The WHOLE page is sent up to the server.

Now your code behind runs. But, ANY changes to a text box, or even viewstate? The user still sees the browser "wait/working spinner" still going.

So, you can loop from 1 to 10, or 1 to whatever. And in that loop, you can change a text box, change view state - it don't matter. The WHOLE PAGE is STILL up on the server.

Only after 100% of your code is done server side, and done making changes to that web page on the server. (and while you make the changes, the end user sees nothing).

Now, the page life cycle completes (the so called round trip).

now the WHOLE NEW FRESH copy of the browser page is send back to the user's desktop.

Like this:

enter image description here

At this point, the WHOLE new page is loaded, JavaScript starts running, and the user NOW sees ANY and ALL changes your code on the server made!

And on the server side? Your web page is disposed, and nuclear bombed out of existance. The page class, and code values and code variables are all gone and destroyed!

The server is now ready to process a web page from ANY user - not just you!!

There is NOT a in-memory copy of your code, nor does any of your code behind variables exist any more. As noted, it is ONE computer. On desktop land, each user has a copy of the program, and their own code, and their own values for variables. But in web land? You have ONE computer. And right after the web server sends that page back to the client side, everything server side goes out of scope, and is disposed/destroyed. The web server is now read to accept any web page from any user.

However, that user might go to stack overflow, might start shopping, or turn off their computer. The web server has ZERO clue that you done this.

So, now, with the above information?

We just learned that code behind NEVER interacts with the user! It can ONLY make changes to the web page with code behind. And those changes occur WHILE the web page is up on the server for that very short time (hopefully short time) that code runs. As that code behind makes changes to the web page?

The end user sees nothing, and sees NO changes to the page. Only after all code runs and a new page is sent back to the client side browser will the end user see any changes. this also tends to mean it don't matter what order your code say updates some text boxes, since ONLY AFTER all code is done and complete does the web page make the trip back to the client side, and re-loads the WHOLE page. (and thus the so called round trip is now complete).

So, this quite much means you can't use viewstate. As noted, how viewstate works, or even a text box? That information travels with the browser (and goes along for that so called "round trip").

so, how can you have some long running server side process run, and show some kind of progress or update on the client side?

Well, we can't use a whole web page round trip, that's for sure!

Worse yet, we really also can't use code behind for that page, since if we click on a button, the whole page goes up to the server, and WILL NOT return until that long running routine is done!!

in most cases, then, about the best solution is to break up the long running process into parts, and then call each part, and show the progress that way.

And in this context, that means we ALSO really don't want a round trip, since the whole new page coming back will mess up our progress.

So, this comes down to

Is this not "too long" of a process, and we can wait during each step, and have some kind of update for each step?

What this means is we need to break this up into "seperate" steps, and call each step.

now, before I post some examples? We could for example start a new process on the server (note how I said new process, not a new thread!). That process then could say update session() (since unlike viewstate, session() is 100% server side). Then in our client side code, we could "poll" or say every 1/2 second ask the server how far done the server side process is.

There is also a 3rd possibility here. You can create what is called a "web socket", and setup a pipeline type of communication between the server, and the client side. Since coding out this by hand can be a "bloatload" of work, then you can use some pre-existing libraries to do this. In asp.net land, then SignalR is the library that most use and adopt.

So, SignalR wraps up a Web Socket and communication system for you. With that system, then you can write some looping code, and "push out" to the client side the progress of how far along the process is. This library code is also rather common used for a chat system in which two users on a web page can talk to each other (since the classic and simple "round trip" of a browser would not work at all for such a update system).

And to be fair, most systems to achieve the above thus require a mix of client side code (JavaScript), and then a further mix of server side code. it can get rather complex rather fast.

So, if you "really" need a system to update the display and browser in "real time"? Then SignalR is you only practical choice. however, it is a complex system, but you can start here:

https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/introduction-to-signalr

So, the above rather "longish" post of mine was done, since you really cannot do ANY kind of web development without grasping that "round trip" concept. Without spending a few minutes to understand the round trip, then web development will seem like Vudu to you.

So, bottom line: code behind updates a copy of the browser on the server, and ONLY for the short while the page is up on the server. During code behind updates, the end user DOES NOT see the changes - only when the WHOLE page comes back, and as a result they will see any and all changes made in "one shot" so to speak.

So, we could then have some type of progress system, but we would require a "round trip" of some sort, and each round trip would have to be ONE of our steps in our long process.

So, let's do an example - using the break up into parts approach.

We drop in a button (our start button).

And we display each step.

I actually think a JavaScript loop + routine is probably better, but we can try a update panel.

So, say some markup like this:

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>

        <div style="float:left">
        <asp:Button ID="cmdStart" runat="server" 
            Text="Start Long Process" CssClass="btn btn-info"
            OnClick="cmdStart_Click" ClientIDMode="Static"
            />
        </div>
        <div style="float:left;margin-left:20px">
        Process Step: 
        <asp:TextBox ID="txtStep" runat="server" style="text-align:center"
            Text="0"
            Width="32px"
            ClientIDMode="Static"
            >
        </asp:TextBox>
            of:
            <asp:Label ID="lblSteps" runat="server" Text="5" ClientIDMode="Static"></asp:Label>


            <div id="pbar" style="width:360px;height:26px">
            </div>
            <div id="pmsgdiv" runat="server"></div>

        </div>

        <script>
            function mybar2() {
            iStep = $('#txtStep').val()
            iSteps = $('#lblSteps').text()
            console.log(iStep)
            console.log(iSteps)
            $('#pbar').progressbar({ value: iStep / iSteps * 100 });
            $('#pbar > div').css({ 'background': 'skyblue' })
            }
        </script>                
    </ContentTemplate>                
</asp:UpdatePanel>

And now code behind is say this:

protected void cmdStart_Click(object sender, EventArgs e)
{
    const int Steps = 5;

    if (Convert.ToInt32(txtStep.Text) > Steps)
    {
        // reset to 0
        txtStep.Text = "0";
    }

    int MyStep = Convert.ToInt32(txtStep.Text);
    // processor 1-5

    switch (MyStep)
    {
        case 0:
            {
                pmsgdiv.InnerText = "Turn power on";
                break;
            }
        case 1:
            {
                System.Threading.Thread.Sleep(3000);

                // step one done, setup step 2 text
                pmsgdiv.InnerText = "Computer Starting";
                break;
            }
        case 2:
            {
                System.Threading.Thread.Sleep(3000);
                pmsgdiv.InnerText = "Computer Ready";
                break;
            }
        case 3:
            {
                System.Threading.Thread.Sleep(2000);
                pmsgdiv.InnerText = "Start fuel flow";
                break;
            }
        case 4:
            {
                System.Threading.Thread.Sleep(3000);
                pmsgdiv.InnerText = "Wait for turbine";
                break;
            }
        case 5:
            {
                // last step - no more messages for next step
                System.Threading.Thread.Sleep(2000);
                break;
            }
    }
        MyStep += 1;
        txtStep.Text = MyStep.ToString();   

    if (MyStep <= Steps) 
    {
        string jscode = "mybar2();$('#cmdStart').click();";
        ScriptManager.RegisterClientScriptBlock(UpdatePanel1, UpdatePanel1.GetType(), "bclick", jscode, true);
        //ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "bclick", jscode, true);            
    }
    else
    {
        pmsgdiv.InnerText = "Done, engine running";
    }
}

So, above is mostly "air code" or proof of concept.

And the result is thus this:

enter image description here

If you really think about the above code, we're still doing "round trips" and we're still doing post-backs.

In fact, what we do is after we setup the message and step? We inject a button click into the browser! So, the whole page goes to client, renders, and then we click a button to run the step!

So, we are still making so called round trips. This post is already too long, but I perhaps in place of above posted a JavaScript + web method call (ajax call), since that in most cases is a better approach to call a web method, but it means you require more JavaScript skills, where as the above "kind of fake it" update panel does not require really any JavaScript skills.

To be fair, in above I used a jQuery.UI for the progress bar. If you don't have jQuery.ui, then remove that progress div.

Keep in mind that the $('btn').click() example js is also jQuery, so make sure you have that installed and available for the page.

In above of course I "faked" a long processing loop with a sleep for each step.