Preface
As long as you have a little understanding of ViewState, you will know that ViewState in Asp.net pages is generally stored in a hidden field of the page:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value=" A bunch of messy things">
When we browse the page source file, we see a lot of messy things (especially when the page has a DataGrid with a large amount of data, or a GridView in ASP.NET 2.0). time, that is ViewState.
Basic knowledge
Because there are some new changes in the persistence storage mechanism of ViewState in ASP.NET 2.0, I will briefly introduce the relevant things.
In ASP.NET 1.1, only the persistence mechanism of the hidden domain of the page is provided, so in some cases, you have to give up using ViewState. Imagine if there are tens of thousands of records in your DataGrid (don’t think this is abnormal) There is no need (someone has encountered it). If ViewState is enabled, are you sure that your IIS server can withstand it and can the network withstand it? Of course, you can change your storage mechanism by overriding the Page.SavePageStateToPersistenceMedium() method, but don't forget to override Page.LoadPageStateFromPersistenceMedium(), they are a pair.
The default view state persistence mechanism in ASP.NET 2.0 still retains state information as a Base64-encoded string in a hidden HTML element on the page (an element with the type attribute set to "hidden"). ASP.NET pages use the HiddenFieldPageStatePersister object to perform this work and an IStateFormatter instance to serialize and deserialize object state information. Or, for mobile clients with limited bandwidth and resources, you can also use the SessionPageStatePersister class to store the view state of the page in the Session object on the server. In fact, there is only one more Session persistence mechanism. Let us save the page state in the Session. in rather than in the page, which is a bandwidth savings.
But if you want to have a deeper understanding of the ViewState persistence mechanism, you should know about the abstract class PageStatePersister. To retain view state on a client that cannot support the existing view state persistence mechanism, you can extend the PageStatePersister class and introduce your own view. State persistence methods, and you can use page adapters to configure ASP.NET applications to use different view state persistence mechanisms based on the type of client to which the page is served. Classes derived from the PageStatePersister class must override the Save abstract method to store view state and control state in the persistence medium, and override the Load method to extract state information. If you need to serialize view state and control state into strings, you can use the IStateFormatter object accessed through the StateFormatter property. It efficiently serializes and deserializes object state information into Base64 encoded strings. You can also override the StateFormatter property to provide your own object state serialization mechanism. How to do this is explained in my code. It is very simple. You will understand after taking a look.
The ViewState persistence mechanism
hidden field
will not be introduced. This is the default one. As stated in the preface.
Session
only needs to override the PageStatePersister property in ASP.NET2.0.
protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(Page);
}
}
If you need to override these two methods of LoadPageStateFromPersistenceMedium in ASP.NET1.1:
protected override object LoadPageStateFromPersistenceMedium()
{
return Session["ViewState"];
}
protected override void SavePageStateToPersistenceMedium(object viewState)
{
Session["ViewState"] = viewState;
RegisterHiddenField("__VIEWSTATE", "");
}
The database (my example is SQL Server2000)
is in ASP1.1. Please pay attention to the purple line below. I don’t know what the use is. It made me depressed for several days. You will understand me later. Depressed. The following code is just copied from my source code. You don't have to write it like this at all, except for those necessary.
protected override void SavePageStateToPersistenceMedium(object state)
{
string viewStateID = "VIEWSTATE#" + Session.SessionID.ToString() + "#" + DateTime.Now.Ticks.ToString();
ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
ClientScript.RegisterHiddenField("__VIEWSTATE","");//Please note
try
{
if (losFormatter == null)
{
losFormatter = new LosFormatter();
}
StringWriter sw = new StringWriter();
losFormatter.Serialize(sw, state);
Common.ViewStateData vsd = new ViewStateData();
vsd.ViewStateID = viewStateID;
vsd.ViewState = sw.ToString();
da = new DataAccess();
string error = da.SaveViewState(vsd);
Response.Write(error);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
protected override object LoadPageStateFromPersistenceMedium()
{
string viewState = string.Empty;
try
{
if (losFormatter == null)
{
losFormatter = new LosFormatter();
}
string stateID = Page.Request["__VIEWSTATE_KEY"].ToString();
da = new DataAccess();
viewState = da.LoadViewState(stateID);
}
catch
{}
return losFormatter.Deserialize(viewState);
}
This line of code is basically OK in ASP2.0. Why is it basic? Because it is the above line ClientScript.RegisterHiddenField("__VIEWSTATE","");
whether there is this line or not, it is the same in Asp.net1.1 It's feasible. I also referred to other people's code and added this line. After adding this line, there is just an extra <input type="hidden" name="__VIEWSTATE" value="" /> on the
page
.
There are two such things in the source file of the page after running. It's okay to remove that line, so I don't understand what the statement is used for. Please tell me clearly. But it doesn’t work in Asp.net2.0. There is the following error:
The state information is invalid for this page and might be corrupted.
Anyway, I was confused at the time. I have never encountered such an error before, and I can’t find anything by searching Google. , yes, I don’t know if that sentence is wrong. I have been depressed for two days and the problem cannot be solved. I am naturally stupid. I track the entire process of saving the view state into the database and reading it from the database. , I couldn't find the error, so I thought about the code again and again, but I was a little confused about that line. Why should the page register a hidden field of "__VIEWSTATE", so I commented out this line, and it actually worked. So I still don't understand what that line is for.
Of course, we can also complete the above functions by writing a new subclass of PageStatePersister, which is new in ASP.NET2.0:
namespace PageAdapter
{
using System;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
public class DatabasePageStatePersister : PageStatePersister
{
public DatabasePageStatePersister(Page page): base(page)
{}
//
// Load ViewState and ControlState.
//
public override void Load()
{
string viewState;
IStateFormatter formatter = this.StateFormatter;
DataAccess da = new DataAccess();
string stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();
viewState = da.LoadViewState(stateID);
Pair statePair = (Pair)formatter.Deserialize(viewState);
ViewState = statePair.First;
ControlState = statePair.Second;
}
//
// Persist any ViewState and ControlState.
//
public override void Save()
{
if (ViewState != null || ControlState != null)
{
if (Page.Session != null)
{
string viewStateID = "VIEWSTATE#" + base.Page.Session.SessionID.ToString() + "#" + DateTime.Now.Ticks.ToString();
base.Page.ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
Pair statePair = new Pair(ViewState, ControlState);
IStateFormatter formatter = this.StateFormatter;
// Serialize the statePair object to a string.
string serializedState = formatter.Serialize(statePair);
ViewStateData vsd = new ViewStateData();
vsd.ViewStateID = viewStateID;
vsd.ViewState = serializedState;
DataAccess da = new DataAccess();
string error = da.SaveViewState(vsd);
}
else
throw new InvalidOperationException("Session needed for StreamPageStatePersister.");
}
}
}
}
Then you can override the PageStatePersister property:
protected override PageStatePersister PageStatePersister
{
get
{
return new DatabasePageStatePersister(Page);
}
the file
is not much different from the database. I am only talking about ASP.NET2.0. It should be similar in ASP.NET1.1, but I have not written the code for debugging:
I still use the method of writing a new subclass of PageStatePersister. :
namespace StreamPageAdapter
{
using System;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
//
// The StreamPageStatePersister is an example view state
// persistence mechanism that persists view and control
// state on the Web server.
//
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
public class StreamPageStatePersister : PageStatePersister
{
public StreamPageStatePersister(Page page): base(page)
{}
//
// Load ViewState and ControlState.
//
public override void Load()
{
Stream stateStream = GetSecureStream();
// Read the state string, using the StateFormatter.
StreamReader reader = new StreamReader(stateStream);
IStateFormatter formatter = this.StateFormatter;
string fileContents = reader.ReadToEnd();
// Deserilize returns the Pair object that is serialized in
// the Save method.
Pair statePair = (Pair)formatter.Deserialize(fileContents);
ViewState = statePair.First;
ControlState = statePair.Second;
reader.Close();
stateStream.Close();
}
//
// Persist any ViewState and ControlState.
//
public override void Save()
{
if (ViewState != null || ControlState != null)
{
if (Page.Session != null)
{
Stream stateStream = GetSecureStream();
StreamWriter writer = new StreamWriter(stateStream);
IStateFormatter formatter = this.StateFormatter;
Pair statePair = new Pair(ViewState, ControlState);
// Serialize the statePair object to a string.
string serializedState = formatter.Serialize(statePair);
writer.Write(serializedState);
writer.Close();
stateStream.Close();
}
else
throw new InvalidOperationException("Session needed for StreamPageStatePersister.");
}
}
// Return a secure Stream for your environment.
private Stream GetSecureStream()
{
string path = @"d:a.txt";
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
return fs;
}
}
}
Just override the PageStatePersister property:
protected override PageStatePersister PageStatePersister
{
get
{
return new StreamPageStatePersister (Page);
}
Through the above brief introduction, we should have some understanding, but what we need to understand is: in ASP.NET1.1 we can only complete the above functions by rewriting age.SavePageStateToPersistenceMedium() and Page.LoadPageStateFromPersistenceMedium(); while in ASP.NET1.1 In ASP.NET2.0, in addition to this, we also complete it by writing a new subclass of PageStatePersister and overriding the PageStatePersister property. I didn't find any difference. Of course, if you read the following content, you will understand that writing a new subclass of PageStatePersister of real use.
Using the Page Adapter
Since the state persistence mechanism is related to adaptive rendering and client-side functionality, MyPageAdapter is provided to activate the DatabasePageStatePersister of the ASP.NET application. Finally, a browser capabilities (.browser) file is provided to enable the MyPageAdapter for a specific class of clients (in this case, the default Web browser).
For these contents, please see the PageAdapter project in the source code I provided. You will understand after reading it.
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
namespace PageAdapter
{
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
public class MyPageAdapter : System.Web.UI.Adapters.PageAdapter
{
public override PageStatePersister GetStatePersister()
{
return new PageAdapter.DatabasePageStatePersister(Page);
}
}
}
Finally, in order to enable the MyPageAdapter adapter, you must create a directory called App_Browsers in the root directory of the ASP.NET application and include a .browser file containing the configuration information (in fact, these are all added when you add it to the project A .browser file will be automatically completed for you by vs2005. The <refID element in the configuration file indicates that the configuration overrides the value specified by the default browser in the Default.browser configuration file. This example uses MyPageAdapter for ASP.NET web pages.
(But usuallyadapters
are not used).
<browser refID="Default" >
<controlAdapters>
<adapter
controlType="System.Web.UI.Page"
adapterType="PageAdapter.MyPageAdapter" />
</controlAdapters>
</browser>
</browsers>
This can be seen in the TestPageAdapter project in the source code. This project is used to demonstrate the page adapter.
The conclusion
is relatively simple, and may not be very clear. As for the advantages and disadvantages of various persistence mechanisms, I have not specifically tested it, and the last item "Use page adapter" is not a persistence mechanism, but uses an adapter, so we will Don't override
the PageStatePersister attribute. It seems to me that it is not very useful, because we can put the action of overriding PageStatePersister in the page base class, and all other pages can inherit this base class. This is how it is in my code. It's troublesome to use this page adapter. Of course, I don't know much about the page adapter.
In addition, a brief explanation of my source code:
1. PageAdapter project
DatabasePageStatePersister.cs: a subclass of the PageStatePersister class MyPageAdapter.cs: page adapter DataAccess.cs and ViewSate.cs database access, belonging to the auxiliary class.
2. The StreamPageAdapter project
is similar to the one above, so I won’t go into details.
3. SaveStateToDatabase project
StateInHiddenField.aspx: Test the default storage mechanism, that is, you can see a lot of messy things when you look at the page source file.
StateInSession.aspx: The storage mechanism is Session.
StateInDatabase.aspx: The storage mechanism database is the type of rewrite method. It can be used by asp.net1.1 and 2.0.
StateInDatabase2.aspx: Write a new subclass of PageStatePersister and override the PageStatePersister property.
StateInFile.aspx: Save ViewState in a folder on the server.
4. TestPageAdater project.
Used for testing and adapters.