Exercise 4: Granular View State

WebForms 4 includes the new ViewStateMode property in the Control class to provide a more granular control over the View State. Granular control of View State means that you can turn it off at the page, and just turn it on for the controls you want. Versus turning it on, and turning it off a million places. So it should be much easier to say: I want it off for the page, turn it on for these three controls, and it’s out of your way.

Task 1 – Disabling ViewState on Controls

In this task, you will disable ViewState at Page level in Default.aspx, and at Control level in ShoppingCart.ascx. This will make possible to have a granular ViewState control in future steps.

  1. Open Microsoft Visual Studio 2010 as an Administrator. Right-click on Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010.and select Run as Administrator.
  2. Open the solution file WebFormsSampleApp.sln located under \Ex04-ViewState\begin\(choosing the folder that matches the language of your preference)

    Note:
    Alternatively, you may continue working with the solution obtained after completing the previous exercise.

    You will be using this unaltered begin solution in the Verificationsection, so consider working on a copy of this begin solution, in order to conserve the original one intact.

  3. Disable ViewState at Page level in Default.aspx. To do this, open Default.aspx in Markup mode, and replace the <% Page %> directive for the following one.

    Note:
    This will result in disabling ViewState for all the child controls in the page. In later steps, you will see how to leverage granular ViewState by enabling it just for the controls that you need within that page.

    ASP.NET (C#)

    <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/UI.master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebFormsSampleApp._Default" EnableViewState="false" %>

    ASP.NET (VB)

    <%@ Page Title="Home Page" Language="Vb" MasterPageFile="~/UI.master" AutoEventWireup="true" CodeBehind="Default.aspx.vb" Inherits="WebFormsSampleApp._Default" EnableViewState="false" %>

  4. Disable ViewState for the shopping cart user control. To do this, open ShoppingCart.ascx in Markup mode (located under UserControls folder), and replace the <% Control %> directive for the following one.

    Note:
    Enabling ViewStateMode for this control would result in a heavy pay load while rendering the page. To avoid this, you will disable ViewStateMode for this control and all its child controls, and handle them from Session.

    ASP.NET (C#)

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ShoppingCart.ascx.cs" Inherits="WebFormsSampleApp.UserControls.ShoppingCartControl" EnableViewState="false" %>

    ASP.NET (VB)

    <%@ Control Language="VB" AutoEventWireup="true" CodeBehind="ShoppingCart.ascx.vb" Inherits="WebFormsSampleApp.UserControls.ShoppingCartControl" EnableViewState="false" %>

Task 2 – Enabling Granular ViewState on Child Controls

In this task, you will modify the way in which some values are stored in ViewState, such as the current category name, the current selected page, and the number of total pages. It is useful to have these values in ViewState for example every time you add an item to the shopping cart, and preserve the exact page state (same category, same page number) after the postback.

You will create three hidden controls, one for each value, and you will take advantage of granular ViewState by enabling ViewState for each of them. As a result, these will be the only fields to be stored in the ViewState for the Default.aspx page, reducing the total size of the page, and increasing the application performance.

Note:
Until now, you were storing these values in the Default.aspx page’s ViewState, but as this functionality was disabled in the previous task, the ViewState collection for this control is no longer available.

  1. Add three new hidden fields to replace the values that were stored on the Page's ViewState. To do this, open Default.aspx in Markup mode, and add the following highlighted code to the second <asp:Content> element.

    Note:
    Although you will use these hidden fields’ ViewState to preserve the values between postbacks, you could have also obtained them based on the URL via ASP.NET Routing (as shown in Exercise 2: Enabling Bi-Directional Routing Support ). However, for practical purposes you will use the hidden field approach in order to show the new ViewStateMode feature.

    ASP.NET

    ...
    FakePre-565c72f6b9bf4a7ebfcf25b4875d5657-aa078b553ba04c04a9b1f828cef2f9a2 <asp:HiddenField ID="CategoryNameState" runat="server" ViewStateMode="Enabled" /> <asp:HiddenField ID="TotalPagesState" runat="server" ViewStateMode="Enabled" /> <asp:HiddenField ID="SelectedPageState" runat="server" ViewStateMode="Enabled" />FakePre-39718e1da18c41b5bed85c8eb9ce036d-13245ced734542be9e3215053745e8dbFakePre-7c665f67d115490c853d6d7fd996cc22-4f9720e27a864dab938a27e7cbf4800e

  2. Enable ViewState in the hidden field that stores the shopping cart state (indicating if it is expanded or collapsed). To do this, set the ViewStateMode property to Enable in the ShoppingCartState HiddenField declaration as shown in the following code.

    ASP.NET

    <asp:HiddenField ID="ShoppingCartState" ClientIDMode="Static" runat="server" ViewStateMode="Enabled" />

Task 3 – Retrieving ViewState Values from Code

In this task, you will change the way in which the SelectedCategoryName, TotalPages and SelectedPage properties are getting/setting their values from code. You will also force to reload the product ListView in every postback, as a consequence of having disabled the ViewState for that control.

  1. Replace the getter and setter implementation of the SelectedCategoryName, TotalPages and SelectedPage properties to get/set the value from/to the hidden fields instead of the ViewState. To do this, open Default.aspx code-behind, and replace the current property definitions with the following highlighted code.

    (Code Snippet – ASP.NET 4 Web Forms Lab – GranularViewState Properties – C#)

    C#

    public string SelectedCategoryName { get { if (this.CategoryNameState.Value == null) { this.CategoryNameState.Value = "Bikes"; } return this.CategoryNameState.Value; } set { this.CategoryNameState.Value = value; } } public int TotalPages { get { if (TotalPagesState.Value == null) { TotalPagesState.Value = "0"; } return Convert.ToInt32(TotalPagesState.Value); } set { TotalPagesState.Value = Convert.ToString(value); } } public int SelectedPage { get { if (this.SelectedPageState.Value == null) { this.SelectedPageState.Value = "1"; } return Convert.ToInt32(this.SelectedPageState.Value); } set { this.SelectedPageState.Value = Convert.ToString(value); } }
    FakePre-be9363697e4241d08de6a1760858e183-a5e6382081984c2b997e560d894e1d44FakePre-3cadfd1838e04474a069f8dbe943880a-d69844f4a1e845a28b5ebb8872840c1bFakePre-a3de4d9f26fc4514a87821342cacc2e8-649fbb16357844a8a84409b22e0fa5fbFakePre-cfb87e2710644ba99f369a930f62afd7-9d2955f05198418f86a163931e3f4a90
    

    (Code Snippet – ASP.NET 4 Web Forms Lab – GranularViewState Properties – VB)

    VB

    Public Property SelectedCategoryName() As String Get If Me.CategoryNameState.Value Is Nothing Then Me.CategoryNameState.Value = "Bikes" End If Return Me.CategoryNameState.Value End Get Set(ByVal value As String) Me.CategoryNameState.Value = value End Set End Property Public Property TotalPages() As Integer Get If TotalPagesState.Value Is Nothing Then TotalPagesState.Value = "0" End If Return Convert.ToInt32(TotalPagesState.Value) End Get Set(ByVal value As Integer) TotalPagesState.Value = Convert.ToString(value) End Set End Property Public Property SelectedPage() As Integer Get If Me.SelectedPageState.Value Is Nothing Then Me.SelectedPageState.Value = "1" End If Return Convert.ToInt32(Me.SelectedPageState.Value) End Get Set(ByVal value As Integer) Me.SelectedPageState.Value = Convert.ToString(value) End Set End Property
    FakePre-74f3a50c637d4168b0f8142766a4c00d-5853e652716249c3b52d58179c193d07FakePre-99f4256983bd48f38531b59a64901034-0b5430d4bd6e42a1ab86a2e653fa745fFakePre-8204ac91a198411a94c849f9cf32bbd5-521c92dc5d86431d9ee4351ff0ee5d35FakePre-8beba64dd2a8479a91a218b509317f87-e94f73214fc041d694b4763be2cb9374
    

  2. Reload the product ListView on every postback. To do this, open Default.aspx.cs file, and inside the Page_Load method move the call to the ApplyProductsFilter method outside the if (!PostBack) conditional clause. The resulting method should look like the following:

    Note:
    While ViewStateMode in Default.aspx was enabled at Page level, all of its child controls were saving ViewState by default including the product ListView. That is why you did not need to reload the products again during postbacks. This incurred substantial increases in the page size rendered to the user.

    (Code Snippet – ASP.NET 4 Web Forms Lab – Page_Load Method – C#)

    C#

    protected void Page_Load(object sender, EventArgs e)
    FakePre-49a5282fb6b349e79e84900c956bbed0-22eba855f709467a90b4266eb11b3cc1 if (!IsPostBack) { this.SelectedCategoryName = GetCategoryName(); this.SelectedPage = GetPageIndex(); } ApplyProductsFilter(); CreatePagerLinks();FakePre-d38950cb26674aabb2af1be205fd5a03-33c18e95b3a04d6d9801547d96cad023FakePre-56664132499f4a8499751a09e81e6f8d-71137da0a7f74c87bdb25634d8e05e73

    (Code Snippet – ASP.NET 4 Web Forms Lab – Page_Load Method – VB)

    C#

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
    If (Not IsPostBack) Then Me.SelectedCategoryName = GetCategoryName() Me.SelectedPage = GetPageIndex() End If ApplyProductsFilter() CreatePagerLinks()FakePre-b444737bfa0d4b52a9af89aa359e3a8d-02dac5c90096456f96f81764f9829a29FakePre-fd7aab77baa8452aaee33a203d65d631-63ee3776f3894fdda8ed5fb1c365c4a3

    Note:
    In this case, you are re-loading the ListView (going against the database) in every postback because no ViewState was stored for this control.

    In a more realistic scenario you should evaluate whether it is more convenient to have an extra payload to store the ViewState for the product’s ListView, rather than making a new round-trip to the database to retrieve the values again, or vice versa.

Next Step

Exercise 4: Verification