The Basics of Creating Server Controls
page 6 of 7
by Justin Lovell
Feedback
Average Rating: 
Views (Total / Last 10 Days): 51626/ 95

View State - Persisting data during Post Backs

In this article, I would only cover the basics of view state. If you do not know what view state is, it is the medium of containing data to persist when the user posts back to the same page. This concept is not new to classic ASP at all. In classic ASP, persisting data for reuse on the same page was a very tedious task - never mind the fact it was normally in clear text. ASP.NET simplifies that process of persisting data so it is as simple to use as the Application state. View state is used by server controls to persist its data across different requests - it is not designed to persist server controls itself, nor its sub controls.

I am not going to write a long talk about "What is view state?" Instead, you can read a very well explained article by Paul Wilson, title “View State: All You Wanted to Know”.

Just a recap of the only rule of view state - what view state is optimized for:

  • Objects (that are one of the following).

  • Integers.

  • Strings.

  • Floats.

  • Decimals.

  • Objects.

  • Pair class containing the above data types or Triplet class.

  • Triplet class containing the above data types.

  • Arrays of the data types stated above.

  • ArrayList with the values being a type of data types listed above.

  • A StateBag containing the values of the data types listed above.

You can create custom optimized classes for ViewState by implementing IStateManager interface but essentially, you will have to drill down your basic string data type. Essentially, a normal XYZ class is not optimal to be put into ViewState without the implementation of the IStateManager interface - it can be done but heavy work will be required to be completed by ASP.NET to be serialized.

Also note that if you are planning to persist a structure, you will have to add the SerializableAttribute attribute to the actual structure.

The normal suggestion of making your properties persist in view state is by making your properties follow the same type of format:

// [C#]
public string FooString {
   get {
      string value = (string)ViewState["FooString"];
      return (value != null) ? (string)value : String.Empty;
   }
   set { ViewState["FooString"] = value; }
}
' [VB.NET]
Public Property FooString() As String
   Get
      Dim value As String = CStr(ViewState("FooString"))
      If Not (value Is Nothing) Then
         Return CStr(value)
      Else
         Return [String].Empty
      End If
   End Get
   Set
      ViewState("FooString") = value
   End Set
End Property

Tiresome isn't it!? But I have a better solution because I am just as lazy like you. Here is the basic "magic" code that will needed by all controls that is going to follow our lazy route:

(Edit: Marvin Slayton gave some feedback on the original source. He managed to pick up a few bugs that the original source allowed to slip through for posting back to the server. To reproduce the error, view state keys that were set before the Init event caused the keys that were later added via the LoadViewState method to throw an exception. He was even kind enough to provide the fix and I have further modified the fix to provide consinstency.)

// [C#]
private const string BaseStateKey = "DefaultViewState";
private Hashtable StateTable = new Hashtable();
protected internal void SaveToStateTable(string key, object value) {
if (StateTable.ContainsKey(key)) StateTable[key] = value.ToString();
else StateTable.Add(key, value.ToString());
}
protected internal object LoadFromStateTable(string key, object defaultValue) {
   if (StateTable.ContainsKey(key))
      return (string)StateTable[key];
   else {
      if ((defaultValue.GetType() != typeof(string)) &&
(defaultValue.GetType() != typeof(ValueType))) {
StateTable.Add(key, defaultValue);
}
      return defaultValue;
}
}
protected override object SaveViewState() {
string[] keys = new string[StateTable.Count];
ArrayList indices = new ArrayList();
ArrayList state = new ArrayList();
StateTable.Keys.CopyTo(keys, 0);
indices.Add(BaseStateKey);
state.Add(base.SaveViewState());
   foreach (string key in keys) {
indices.Add(key);
state.Add(StateTable[key]);
}
   return new Pair(indices, state);
}
protected override void LoadViewState(object state) {
if (state == null) return;
   ArrayList indices = ((Pair)state).First as ArrayList;
ArrayList values = ((Pair)state).Second as ArrayList;
   for (int i = 0; i < indices.Count; i++) {
if (indices[i].ToString() == BaseStateKey)
base.LoadViewState(values[i]);
else
SaveToStateTable(indices[i].ToString(), values[i]);
}
}
' [VB.NET]
Private Const BaseStateKey As String = "DefaultViewState"
Private StateTable As New Hashtable()
Friend Protected Sub SaveToStateTable(key As String, value As Object)
   If StateTable.ContainsKey(key) Then
      StateTable(key) = value.ToString()
   Else
      StateTable.Add(key, value.ToString())
   End If
End Sub
 
Friend Protected Function LoadFromStateTable(key As String, _
defaultValue As Object) As Object
   If StateTable.ContainsKey(key) Then
      Return CStr(StateTable(key))
   Else
      If defaultValue.GetType() <> GetType(String) And _
defaultValue.GetType() <> GetType(ValueType) Then
         StateTable.Add(key, defaultValue)
      End If
     
      Return defaultValue
   End If
End Function
Protected Overrides Function SaveViewState() As Object
   Dim keys(StateTable.Count) As String
   Dim indices As New ArrayList()
   Dim state As New ArrayList()
   StateTable.Keys.CopyTo(keys, 0)
   indices.Add(BaseStateKey)
   state.Add(MyBase.SaveViewState())
  
   For Each key As String In  keys
      indices.Add(key)
      state.Add(StateTable(key))
   Next
  
   Return New Pair(indices, state)
End Function
Protected Overrides Sub LoadViewState(state As Object)
   If state Is Nothing Then
      Return
   End If
   Dim indices As ArrayList = CType(CType(state, Pair).First, ArrayList)
   Dim values As ArrayList = CType(CType(state, Pair).Second, ArrayList)
  
   For i As Integer = 0 To indices.Count - 1
      If indices(i).ToString() = BaseStateKey Then
         MyBase.LoadViewState(values(i))
      Else
         SaveToStateTable(indices(i).ToString(), values(i))
      End If
   Next
End Sub

With this code, we will save the default view state with the custom view state. We also added the feature that advanced data types will be automatically added to the view state bin if it does not exist in the bin. If it does, any changes to the data inside itself will remain persistent. Now I am going to demonstrate the same functionality that the code before my magic hand was used with the new, improved, lazy format:

// [C#]
public string FooString {
   get { return (string)LoadFromStateTable("FooString", String.Empty); }
   set { SaveToStateTable("FooString", value); }
}
' [VB.NET]
Public Property FooString() As String
   Get
      Return CStr(LoadFromStateTable("FooString", [String].Empty))
   End Get
   Set
      SaveToStateTable("FooString", value)
   End Set
End Property

For more advanced data types such as classes, you can still use this lazy method. Instead of defining a default value such as a "0", you would create a new instance of that data type (by its constructor). Please remember, for optimal performance, ensure that the class implements IStateManager interface for the view state to deserialize the object a lot quicker.

I will discuss further into view state and handling it at a later article in the series. Depending on the feedback I receive and the topics and content of the threads at the www.asp.net/forums/, will determine the depth that it will be discussed in the future.


View Entire Article

User Comments

Title: How do I put this control on a page?   
Name: G Shields
Date: 2010-07-21 11:53:01 PM
Comment:
Okay, so I have the inherited custom control class. How do I put it in my page?
Title: Need a translator   
Name: Rob
Date: 2009-05-18 2:24:18 PM
Comment:
Overall I found this article helpful, in some places though the English is so bad that it is practically illegible. As a result, I may have missed some of the finer points.
Title: Simply The Great   
Name: Dot Net Lover
Date: 2008-12-18 10:26:30 PM
Comment:
An Excellent Article.
Thanx for writing.
10 out of 10.
Title: Spell check please   
Name: bszom
Date: 2007-05-23 4:33:57 AM
Comment:
Lame-man's terms? Please, this article would be 3x as good had it been spell-checked.
Title: BRILLIANT explanations and structure!   
Name: Magnus B
Date: 2007-01-26 11:56:21 AM
Comment:
Thank you for gathering what I need to know in such a professional and independent page. Just the way I would ;)
Title: Good work   
Name: Narendra S. Jakhotia
Date: 2006-11-07 4:50:52 AM
Comment:
this topic Cleared most of my concepts on creating controls. I need help from U . I want to combine properties of Image button and Label please tell me how can I do it?
If possible please help me out.naren_pict@yahoo.co.in
Title: Excellent Example   
Name: Jayesh Chudasama
Date: 2006-09-01 2:22:23 AM
Comment:
Great Example!! It outlines all basic needs to understand to create server control.
Title: The Basics of Creating Server Controls   
Name: Jan Waiz
Date: 2005-08-04 11:53:17 AM
Comment:
Perfect!
Title: your history on classic ASP   
Name: JP
Date: 2005-08-03 3:42:12 AM
Comment:
You history on Classic ASP is not quite right. Classic ASP supported use of functions and subroutines which allowed code to be placed anywhere in your page. It also supported use of code classes and window script components (WSC). WSC files are components in XML format which did not have to be registered on the server.

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-25 4:00:55 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search