View state is the means by which controls on a page can maintain state information between requests. HTTP is inherently stateless, so additional coding needed to be done to allow a control's state to persist between multiple requests for the same page. For example, if a user selects the third item in a drop-down list, checks a box, and enters some text in a text box, you will want that information to be made available to you in your server code so that you can process it, validate it, or persist the information in a database.
This is all made possible using the mechanism called view state. When a page is almost finished its rendering phase, it creates a hidden form field called __VIEWSTATE. This hidden input tag contains the state for all controls on the entire page in a serialized fashion. When you view the source for an ASP.NET page, you will see the view state tag as shown in the following code:
<input type="hidden" name="__VIEWSTATE" value="..."/>
View state is restored from this hidden input tag during the initialization phase of the page life cycle and made available to the developer in the ViewState property of the Page class. The ViewState property is an instance of the StateBag class.
To place a value into view state to be restored on a subsequent postback, you can use indexer notation as shown in the following code:
ViewState["customValue"] = 21;
And then on a subsequent postback, you can check the value you stored with the following code:
if (Page.IsPostback) if (ViewState["customValue"] != null) Response.Write(ViewState["customValue"]);
As long as you know when view state is restored and saved, you will find it easy to work with. If you attempt to access view state before the initialization stage of the page life cycle or attempt to change view state after the rendering stage, the results will be unpredictable. View state is not dynamic like session state. It is restored once at page initialization, and output in the form of a hidden input tag once at page render completion.
As you will see in Chapter 30, "Developing ASP.NET Controls," controls maintain their own state using the ViewState collection. For example, the ListBox control stores the list of items in the list box in view state, and it stores the currently selected item. This allows a page to access the database once to retrieve the data, and then pass the data to subsequent requests using view state, creating a faster and more scalable solution. This pattern is used in virtually all ASP.NET controls.
Despite the power and flexibility that view state provides, it can be overused. Using view state to store large amounts of data can cause problems for users with slower connections.
In a hypothetical scenario, a page retrieves 3,000 rows of data and then instructs a GridView control to render page 3, displaying 20 rows. If this GridView is maintaining the entire set of data between requests, the GridView will actually be placing 3,000 rows of data into view state. As a rule of thumb, storing data in view state actually consumes more space than the raw value. Therefore, storing a 32-bit integer in view state is going to consume far more data than just 4 bytes because the name of the view state item is also stored in view state.
In a production application, you will probably find that you need to reach a balance. Using view state for every control on your page regardless of whether its value needs to be persisted between requests can lead to a severe bloating of the view state hidden form field (which increases page size as a result). Querying the database on every request is also going to cause problems for your database.
What most developers do is find middle ground. They will disable view state for all controls that have static values or values that are irrelevant on postback. Developers can also do things like only query a single page of data from the database so that only a small number of rows are stored in view state. It will be up to you to find the middle ground that satisfies your performance, scalability, and time-to-market requirements.
One approach that seems to work well is to get the initial version of a page done relying heavily on view state and default data-binding code. When the initial version is completed, you can analyze the size of the view state (figure out how long it takes to download view state on the slowest end-user connection) and determine how much view state (if any) you need to trim from the page to decrease download time. One thing you never want to do is waste weeks of development time to create a performance improvement that most users won't be able to see. Always weigh the cost of improvement against visible benefits to the end user.