Préface
Tant que vous aurez un peu de compréhension de ViewState, vous saurez que ViewState dans les pages Asp.net est généralement stocké dans un champ caché de la page :
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value=" Un tas de choses compliquées">
Lorsque nous parcourons le fichier source de la page, nous voyons beaucoup de choses compliquées (surtout lorsque la page a un DataGrid avec une grande quantité de données, ou un GridView dans ASP.NET 2.0). le temps, c'est ViewState.
Connaissances de base
Étant donné qu'il y a de nouveaux changements dans le mécanisme de stockage de persistance de ViewState dans ASP.NET 2.0, je présenterai brièvement les éléments pertinents.
Dans ASP.NET 1.1, seul le mécanisme de persistance du domaine caché de la page est fourni, donc dans certains cas, vous devez renoncer à utiliser ViewState. Imaginez s'il y a des dizaines de milliers d'enregistrements dans votre DataGrid (n'y pensez pas). c'est anormal) Ce n'est pas nécessaire (quelqu'un l'a rencontré). Si ViewState est activé, êtes-vous sûr que votre serveur IIS peut y résister et que le réseau peut y résister ? Bien sûr, vous pouvez modifier votre mécanisme de stockage en remplaçant la méthode Page.SavePageStateToPersistenceMedium(), mais n'oubliez pas de remplacer Page.LoadPageStateFromPersistenceMedium(), ils forment une paire.
Le mécanisme de persistance de l'état d'affichage par défaut dans ASP.NET 2.0 conserve toujours les informations d'état sous forme de chaîne codée en Base64 dans un élément HTML masqué sur la page (un élément dont l'attribut type est défini sur « caché »). Les pages ASP.NET utilisent l'objet HiddenFieldPageStatePersister pour effectuer ce travail et une instance IStateFormatter pour sérialiser et désérialiser les informations sur l'état de l'objet. Ou, pour les clients mobiles avec une bande passante et des ressources limitées, vous pouvez également utiliser la classe SessionPageStatePersister pour stocker l'état d'affichage de la page dans l'objet Session sur le serveur. En fait, il n'y a qu'un seul mécanisme de persistance de session supplémentaire. état de la page dans la session plutôt que dans la page, ce qui représente une économie de bande passante.
Mais si vous souhaitez mieux comprendre le mécanisme de persistance ViewState, vous devez connaître la classe abstraite PageStatePersister. Pour conserver l'état d'affichage sur un client qui ne peut pas prendre en charge le mécanisme de persistance de l'état d'affichage existant, vous pouvez étendre la classe PageStatePersister et introduire votre vous pouvez utiliser vos propres méthodes de persistance d’état et vous pouvez utiliser des adaptateurs de page pour configurer les applications ASP.NET afin d’utiliser différents mécanismes de persistance d’état d’affichage en fonction du type de client auquel la page est servie. Les classes dérivées de la classe PageStatePersister doivent remplacer la méthode abstraite Save pour stocker l'état d'affichage et l'état de contrôle dans le support de persistance, et remplacer la méthode Load pour extraire les informations d'état. Si vous devez sérialiser l'état d'affichage et l'état de contrôle en chaînes, vous pouvez utiliser l'objet IStateFormatter accessible via la propriété StateFormatter. Il sérialise et désérialise efficacement les informations sur l'état des objets en chaînes codées en Base64. Vous pouvez également remplacer la propriété StateFormatter pour fournir votre propre mécanisme de sérialisation de l'état des objets. Comment procéder est expliqué dans mon code. Vous comprendrez après y avoir jeté un coup d'œil.
Le
champ caché
du mécanisme de persistance ViewStatene sera pas introduit. Il s'agit de celui par défaut. Comme indiqué dans la préface.
La session
doit uniquement remplacer la propriété PageStatePersister dans ASP.NET2.0.
remplacement protégé PageStatePersister PageStatePersister
{
obtenir
{
renvoie un nouveau SessionPageStatePersister (Page);
}
}
Si vous devez remplacer ces deux méthodes de LoadPageStateFromPersistenceMedium dans ASP.NET1.1 :
objet de remplacement protégé LoadPageStateFromPersistenceMedium()
{
retourner Session["ViewState"] ;
}
remplacement protégé void SavePageStateToPersistenceMedium (object viewState)
{
Session["ViewState"] = viewState;
RegisterHiddenField("__VIEWSTATE", "");
}
La base de données (mon exemple est SQL Server2000)
est en ASP1.1. Veuillez faire attention à la ligne violette ci-dessous. Je ne sais pas à quoi ça sert. Cela m'a déprimé pendant plusieurs jours. . Le code suivant est simplement copié de mon code source. Vous n'êtes pas du tout obligé de l'écrire comme ça, sauf pour ceux qui sont nécessaires.
remplacement protégé void SavePageStateToPersistenceMedium (état de l'objet)
{
chaîne viewStateID = "VIEWSTATE#" + Session.SessionID.ToString() + "#" + DateTime.Now.Ticks.ToString();
ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
ClientScript.RegisterHiddenField("__VIEWSTATE","");//Veuillez noter
que vous essayez
{
si (losFormatter == null)
{
losFormatter = nouveau LosFormatter();
}
StringWriter sw = new StringWriter();
losFormatter.Serialize(logiciel, état);
Common.ViewStateData vsd = new ViewStateData();
vsd.ViewStateID = viewStateID ;
vsd.ViewState = sw.ToString();
da = nouveau DataAccess();
erreur de chaîne = da.SaveViewState(vsd);
Réponse.Write (erreur);
}
attraper (Exception ex)
{
Response.Write (ex.Message);
}
}
objet de remplacement protégé LoadPageStateFromPersistenceMedium()
{
string viewState = string.Empty;
essayer
{
si (losFormatter == null)
{
losFormatter = nouveau LosFormatter();
}
chaîne stateID = Page.Request["__VIEWSTATE_KEY"].ToString();
da = nouveau DataAccess();
viewState = da.LoadViewState(stateID);
}
attraper
{}
return losFormatter.Deserialize(viewState);
}
Cette ligne de code est fondamentalement OK dans ASP2.0. Pourquoi est-elle basique ? Parce que c'est la ligne ci-dessus ClientScript.RegisterHiddenField("__VIEWSTATE","")
; .net1.1 C'est faisable. J'ai également fait référence au code d'autres personnes et ajouté cette ligne. Après avoir ajouté cette ligne, il y a juste un <input type="hidden" name="__VIEWSTATE" value="" /> supplémentaire sur la
page.
.
Il y a deux éléments de ce type dans le fichier source de la page après l'exécution. Vous pouvez supprimer cette ligne, donc je ne comprends pas à quoi sert la déclaration. Veuillez me le dire clairement. Mais cela ne fonctionne pas dans Asp.net2.0. Il y a l'erreur suivante :
Les informations d'état ne sont pas valides pour cette page et peuvent être corrompues.
Quoi qu'il en soit, j'étais confus à l'époque, je n'avais jamais rencontré une telle erreur auparavant. et je ne trouve rien en cherchant sur Google, oui, je ne sais pas si cette phrase est fausse. Je suis déprimé depuis deux jours et le problème ne peut pas être résolu. Je suis naturellement stupide. en enregistrant l'état d'affichage dans la base de données et en le lisant à partir de la base de données, je n'ai pas trouvé l'erreur, alors j'ai pensé au code encore et encore, mais j'étais un peu confus à propos de cette ligne. Pourquoi la page devrait-elle enregistrer un message caché. champ de "__VIEWSTATE", j'ai donc commenté cette ligne, et cela a réellement fonctionné, donc je ne comprends toujours pas à quoi sert cette ligne.
Bien entendu, nous pouvons également compléter les fonctions ci-dessus en écrivant une nouvelle sous-classe de PageStatePersister, qui est nouvelle dans ASP.NET2.0 :
l'espace de noms PageAdapter.
{
utiliser le système ;
en utilisant System.IO ;
en utilisant System.Security.Permissions ;
en utilisant System.Web ;
en utilisant System.Web.UI ;
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
classe publique DatabasePageStatePersister : PageStatePersister
{
public DatabasePageStatePersister (page page): base (page)
{}
//
// Charge ViewState et ControlState.
//
remplacement public void Load()
{
chaîne viewState ;
IStateFormatter formateur = this.StateFormatter;
DataAccess da = new DataAccess();
chaîne stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();
viewState = da.LoadViewState(stateID);
Paire statePair = (Pair)formatter.Deserialize(viewState);
ViewState = statePair.First ;
ControlState = statePair.Second ;
}
//
// Conserve tous les ViewState et ControlState.
//
remplacement public void Save()
{
si (ViewState != null || ControlState != null)
{
si (Page.Session != null)
{
chaîne viewStateID = "VIEWSTATE#" + base.Page.Session.SessionID.ToString() + "#" + DateTime.Now.Ticks.ToString();
base.Page.ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
Paire statePair = new Pair(ViewState, ControlState);
IStateFormatter formateur = this.StateFormatter;
// Sérialise l'objet statePair en une chaîne.
string serializedState = formateur.Serialize(statePair);
ViewStateData vsd = new ViewStateData();
vsd.ViewStateID = viewStateID ;
vsd.ViewState = serializedState ;
DataAccess da = new DataAccess();
erreur de chaîne = da.SaveViewState(vsd);
}
autre
throw new InvalidOperationException("Session nécessaire pour StreamPageStatePersister.");
}
}
}
}
Ensuite, vous pouvez remplacer la propriété PageStatePersister :
protected override PageStatePersister PageStatePersister
{
obtenir
{
renvoie un nouveau DatabasePageStatePersister (Page);
}
le fichier
n'est pas très différent de la base de données. Je parle uniquement d'ASP.NET2.0. Il devrait être similaire dans ASP.NET1.1, mais je n'ai pas écrit le code pour le débogage :
j'utilise toujours la méthode. d'écrire une nouvelle sous-classe de PageStatePersister :
espace de noms StreamPageAdapter.
{
utiliser le système ;
en utilisant System.IO ;
en utilisant System.Security.Permissions ;
en utilisant System.Web ;
en utilisant System.Web.UI
;
// StreamPageStatePersister est un exemple d'état d'affichage
// mécanisme de persistance qui conserve la vue et le contrôle
// état sur le serveur Web.
//
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
classe publique StreamPageStatePersister : PageStatePersister
{
public StreamPageStatePersister (page page): base (page)
{}
//
// Charge ViewState et ControlState.
//
remplacement public void Load()
{
Flux stateStream = GetSecureStream();
// Lit la chaîne d'état à l'aide de StateFormatter.
Lecteur StreamReader = new StreamReader (stateStream);
IStateFormatter formateur = this.StateFormatter;
chaîne fileContents = reader.ReadToEnd();
// Deserilize renvoie l'objet Pair qui est sérialisé dans
// la méthode Save.
Paire statePair = (Pair)formatter.Deserialize(fileContents);
ViewState = statePair.First ;
ControlState = statePair.Second ;
lecteur.Close();
stateStream.Close();
}
//
// Conserve tous les ViewState et ControlState.
//
remplacement public void Save()
{
si (ViewState != null || ControlState != null)
{
si (Page.Session != null)
{
Flux stateStream = GetSecureStream();
Writer StreamWriter = new StreamWriter(stateStream);
IStateFormatter formateur = this.StateFormatter;
Pair statePair = new Pair(ViewState, ControlState);
// Sérialise l'objet statePair en une chaîne.
chaîne serializedState = formateur.Serialize(statePair);
écrivain.Write(serializedState);
écrivain.Close();
stateStream.Close();
}
autre
throw new InvalidOperationException("Session nécessaire pour StreamPageStatePersister.");
}
}
// Renvoie un Stream sécurisé pour votre environnement
privé GetSecureStream().
{
chemin de chaîne = @"d:a.txt";
FileStream fs = new FileStream(chemin, FileMode.Open, FileAccess.ReadWrite);
retourner fs ;
}
}
}
Remplacez simplement la propriété PageStatePersister :
protected override PageStatePersister PageStatePersister
{
obtenir
{
renvoie le nouveau StreamPageStatePersister (Page }
)
Grâce à la brève introduction ci-dessus, nous devrions avoir une certaine compréhension, mais ce que nous devons comprendre est : dans ASP.NET1.1, nous ne pouvons compléter les fonctions ci-dessus qu'en réécrivant age.SavePageStateToPersistenceMedium() et Page.LoadPageStateFromPersistenceMedium(); .NET1.1 Dans ASP.NET2.0, en plus de cela, nous le complétons également en écrivant une nouvelle sous-classe de PageStatePersister et en remplaçant la propriété PageStatePersister. Bien sûr, si vous lisez le contenu suivant. , vous comprendrez qu'écrire une nouvelle sous-classe de PageStatePersister est d'une réelle utilité.
Utilisation de l'adaptateur de page
Étant donné que le mécanisme de persistance d'état est lié au rendu adaptatif et aux fonctionnalités côté client, MyPageAdapter est fourni pour activer le DatabasePageStatePersister de l'application ASP.NET. Enfin, un fichier de fonctionnalités de navigateur (.browser) est fourni pour activer MyPageAdapter pour une classe spécifique de clients (dans ce cas, le navigateur Web par défaut).
Pour ces contenus, veuillez consulter le projet PageAdapter dans le code source que j'ai fourni. Vous comprendrez après l’avoir lu.
en utilisant System.Security.Permissions ;
en utilisant System.Web ;
l'espace de noms
System.Web.UI ;
{
[AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
classe publique MyPageAdapter : System.Web.UI.Adapters.PageAdapter
{
remplacement public PageStatePersister GetStatePersister()
{
renvoie un nouveau PageAdapter.DatabasePageStatePersister(Page);
}
}
}
Enfin, afin d'activer l'adaptateur MyPageAdapter, vous devez créer un répertoire appelé App_Browsers dans le répertoire racine de l'application ASP.NET et inclure un fichier .browser contenant les informations de configuration (en fait, celles-ci sont toutes ajoutées lorsque vous l'ajoutez au projet Un fichier .browser sera automatiquement complété pour vous par vs2005. L'élément <refID dans le fichier de configuration indique que la configuration remplace la valeur spécifiée par le navigateur par défaut dans le fichier de configuration Default.browser. Pages Web .NET (mais généralement
les adaptateurs
ne sont pas utilisés).
<réfID du navigateur="Par défaut" >
<Adaptateurs de contrôle>
<adaptateur
controlType="Système.Web.UI.Page"
adapterType="PageAdapter.MyPageAdapter" />
</adaptateurs de contrôle>
</navigateur>
</navigateurs>
Cela peut être vu dans le projet TestPageAdapter dans le code source. Ce projet est utilisé pour démontrer l'adaptateur de page.
La conclusion
est relativement simple et peut ne pas être très claire. Quant aux avantages et inconvénients des différents mécanismes de persistance, je ne l'ai pas testé spécifiquement, et le dernier élément « Utiliser l'adaptateur de page » n'est pas un mécanisme de persistance, mais utilise un adaptateur. , nous ne remplacerons donc pas
l'attribut PageStatePersister. Il me semble que ce n'est pas très utile, car nous pouvons mettre l'action de remplacement de PageStatePersister dans la classe de base de la page, et toutes les autres pages peuvent hériter de cette classe de base. comment c'est dans mon code. C'est gênant d'utiliser cet adaptateur de page. Bien sûr, je ne connais pas grand-chose à l'adaptateur de page.
De plus, une brève explication de mon code source :
1. Projet PageAdapter
DatabasePageStatePersister.cs : une sous-classe de la classe PageStatePersister MyPageAdapter.cs : adaptateur de page accès à la base de données DataAccess.cs et ViewSate.cs, appartenant à la classe auxiliaire.
2. Le projet StreamPageAdapter
est similaire à celui ci-dessus, je n'entrerai donc pas dans les détails
3. Projet SaveStateToDatabase
StateInHiddenField.aspx : testez le mécanisme de stockage par défaut, c'est-à-dire que vous pouvez voir beaucoup de choses compliquées lorsque vous regardez. le fichier source de la page.
StateInSession.aspx : Le mécanisme de stockage est Session
StateInDatabase.aspx : La base de données du mécanisme de stockage est le type de méthode de réécriture. Elle peut être utilisée par asp.net1.1 et 2.0.
StateInDatabase2.aspx : écrivez une nouvelle sous-classe de PageStatePersister et remplacez la propriété PageStatePersister.
StateInFile.aspx : enregistrez ViewState dans un dossier sur le serveur.
4. Projet TestPageAdater.
Utilisé pour les tests et les adaptateurs.