1. Introduction de base aux scripts serveur
Tout d'abord, passons en revue les méthodes d'exécution de base des pages du serveur Web :
1. Le client envoie une requête au serveur en tapant l'adresse dans la barre d'adresse du navigateur
2. Une fois que le serveur a reçu la requête, il l'envoie à La page côté serveur correspondante (c'est-à-dire un script) est exécutée. Le script génère une réponse du client et la renvoie au client.
3. Le navigateur client reçoit la réponse du serveur, analyse la. HTML et présente la page Web graphique à l'utilisateur. Pour
l'interaction entre le serveur et le client, les principales méthodes suivantes sont généralement utilisées :
1. Formulaire : il s'agit de la méthode la plus importante utilisée pour obtenir la saisie de l'utilisateur. La soumission du formulaire envoie les données au serveur pour traitement.
2.QueryString
: En ajoutant des paramètres après l'URL, les paramètres sont transmis au serveur. Cette méthode est en fait la même que la méthode Get.
une méthode spéciale, généralement utilisée pour confirmer l'identité de l'utilisateur
. 2. Introduction à ASP.Net
Les langages de script serveur traditionnels, tels que ASP, JSP, etc., écrivent des scripts serveur de la même manière. Ils intègrent tous des codes interprétés ou compilés et exécutés. en HTML, et la plate-forme serveur exécute ces codes pour générer du HTML ; pour des scripts similaires, des pages Le cycle de vie du Servlet est en fait très simple, c'est-à-dire que tout le code est exécuté du début à la fin. Bien sûr, le Servlet est écrit en HTML. Java peut écrire du code plus complexe, mais d'un point de vue structurel, il n'est pas différent de JSP.
L'émergence d'ASP.Net a brisé cette tradition ; ASP.Net a adopté la technologie CodeBehind et les contrôles côté serveur, a ajouté le concept d'événements côté serveur, a modifié le modèle d'écriture du langage de script et s'est rapproché de la programmation Windows, facilitant ainsi la programmation Web. , intuitif ; mais nous devons voir qu'ASP.Net lui-même ne change pas le modèle de base de la programmation Web, il encapsule simplement certains détails et fournit des fonctions faciles à utiliser, rendant le code plus facile à écrire et à maintenir dans une certaine mesure ; extend , compliquant le mode d'exécution côté serveur. C'est le sujet principal dont nous allons discuter aujourd'hui : le cycle de vie de la page Web ASP.Net.
3. Mode de traitement des requêtes ASP.Net
Nous disons que la page Web d'ASP.Net ne rompt pas avec le mode de programmation Web, elle fonctionne donc toujours en mode requête-> recevoir une requête-> traiter une requête-> envoyer une réponse. avec le client déclenchera une nouvelle requête, le cycle de vie d'une page Web est donc basé sur une seule requête.
Lorsque IIS reçoit une demande du client, il transmet la demande au processus aspnet_wp pour traitement. Ce processus vérifiera si le domaine d'application demandé existe. S'il n'existe pas, il en créera un, puis créera un runtime HTTP (. HttpRuntime ) pour gérer les requêtes, ce runtime « fournit un ensemble de services d'exécution ASP.NET pour l'application actuelle » (de MSDN).
Lorsque HttpRuntime traite les demandes, il conservera une série d'instances d'application, c'est-à-dire des instances de la classe Global de l'application (global.asax). Ces instances seront stockées dans un pool d'applications lorsqu'il n'y a aucune demande (en fait, le pool d'applications est maintenu). par une autre classe, HttpRuntime n'est qu'un simple appel). Chaque fois qu'une demande est reçue, HttpRuntime obtiendra une instance inactive pour traiter la demande avant la fin du traitement. revenez au pool, "Une instance est utilisée pour gérer plusieurs requêtes au cours de sa durée de vie, mais elle ne peut gérer qu'une seule requête à la fois." (Extrait de MSDN)
Lorsque l'instance d'application gère la requête, elle crée une instance de la classe de page de requête et exécutez sa méthode ProcessRequest pour traiter la requête. Cette méthode constitue le début du cycle de vie de la page Web.
4. Page Aspx et CodeBehind
Avant de nous plonger dans le cycle de vie de la page, discutons d'abord de certaines des relations entre Aspx et CodeBehind.
<%@ Page language="c#" Codebehind="WebForm.aspx.cs" Inherits="MyNamespace.WebForm" %>
Je pense que les amis qui ont utilisé la technologie CodeBehind devraient être très familiers avec cette phrase en haut d'ASPX. Analysez-le un par un :
Page Language="c#" Inutile de dire que
Codebehind="WebForm.aspx.cs" Cette phrase indique le fichier de code lié
Inherits="MyNamespace.WebForm" Cette phrase est très importante. Elle représente le nom de la classe. héritée par la page, qui est la classe du fichier de code de CodeBehind. Cette classe doit être dérivée de System.Web.WebControls.Page.
De ce qui précède, nous pouvons analyser qu'en fait, la classe de CodeBehind est la base de la page. (ASPX). À ce stade, certains amis voudront peut-être demander. Lors de l'écriture d'ASPX, vous intégrez du code ou des contrôles serveur dans Html exactement selon la méthode ASP. Vous ne voyez pas l'ombre des soi-disant "classes". ?
Ce problème n'est en réalité pas compliqué. Les amis qui utilisent la programmation ASP.Net peuvent accéder à votre disque système : WINDOWSMicrosoft.NETFramework<numéro de version>Fichiers ASP.NET temporaires et le placer sous Tous les fichiers temporaires d'ASP. Applications .Net qui existent sur cette machine. Le nom du sous-répertoire est le nom de l'application, puis descendez de deux niveaux (afin de garantir l'unicité, ASP.Net génère automatiquement deux niveaux de sous-répertoires, et le sous-répertoire Le nom est aléatoire), puis nous constaterons qu'il existe de nombreuses bibliothèques de liens similaires à : "yfy1gjhc.dll", "xeunj5u3.dll" et des sources telles que "komee-bp.0.cs" et "9falckav.0.cs" , en fait, c'est le résultat de la compilation dynamique d'ASPX par ASP.Net. Lorsque nous ouvrons ces fichiers sources, nous pouvons trouver :
classe
publique WebForm_aspx : MyNamespace.WebForm, System.Web.SessionState.IRequiresSessionState.
, ASPX C'est une sous-classe de la classe de liaison de code. Son nom est le nom du fichier ASPX plus le suffixe "_aspx". En étudiant ces codes, nous pouvons constater qu'en fait tous les contrôles serveur définis dans aspx sont générés dans ces codes, et puis lorsque ces codes sont générés dynamiquement, le code initialement intégré dans ASPX est écrit à l'emplacement correspondant.
Lorsqu'une page est visitée pour la première fois, le runtime HTTP utilisera un générateur de code pour analyser le fichier ASPX, générer le code source et le compiler. Ensuite, les visites ultérieures appelleront directement la DLL compilée. C'est pourquoi ASPX est la raison pour laquelle l'accès. est très lent.
Après avoir expliqué ce problème, examinons un autre problème. Lorsque nous utilisons la liaison de code, faites glisser un contrôle sur la page de conception, puis passez à la vue code, vous pouvez utiliser le contrôle directement dans Page_Load Puisque le contrôle est généré dans la sous-classe, pourquoi peut-il être utilisé dans la classe parent ? Et si on l'utilisait directement ?
En fait, nouspouvons
constater que chaque fois que nous utilisons VS.Net pour faire glisser un contrôle sur la page, une instruction similaire à celle-ci est toujours ajoutée au fichier de liaison de code :
protected System.Web.WebControls.Button Button1;
Le champ est Déclarez-le comme protégé et le nom est cohérent avec l'ID du contrôle dans ASPX. Si vous y réfléchissez bien, ce problème sera résolu. Nous avons mentionné plus tôt que le code source d'ASPX est généré et compilé dynamiquement par le générateur. Le générateur générera le code pour générer dynamiquement chaque contrôle serveur lors de la génération, il vérifiera si la classe parent a déclaré ce contrôle. il ajoutera un code similaire au suivant :
this.DataGrid1 = __ctrl;
Ce __ctrl est la variable qui génère le contrôle A ce moment, il attribue la référence du contrôle à la variable correspondante dans la classe parent, c'est pourquoi dans. la classe parent La déclaration doit être protégée (en fait elle peut aussi être publique), car il faut s'assurer que les sous-classes puissent l'appeler.
Ensuite, lorsque Page_Load est exécuté, parce que la déclaration de la classe parent s'est vu attribuer une valeur par le code d'initialisation dans la sous-classe, nous pouvons utiliser ce champ pour accéder au contrôle correspondant. Sachant cela, nous ne validerons pas la liaison de code en utilisant le contrôle. dans le constructeur du fichier spécifié provoque une erreur d'exception de référence nulle. Étant donné que le constructeur est exécuté en premier, l'initialisation de la sous-classe n'a pas encore commencé, donc les champs de la classe parent ont des valeurs nulles. Quant à la sous-classe, nous en discuterons plus tard. lorsqu'une classe est initialisée.
5. Cycle de vie de la page
Revenons maintenant au contenu mentionné dans le troisième titre, nous avons parlé de l'instance de HttpApplication recevant la requête et créant une instance de la classe page. En fait, cette instance est une instance de la classe ASPX compilée dynamiquement. Dans le titre précédent, nous avons appris qu'ASPX est en fait une sous-classe de la classe dans la liaison de code, elle hérite donc de toutes les méthodes protégées.
Jetons maintenant un coup d'œil au code de la classe CodeBehind généré automatiquement par VS.Net pour commencer notre discussion sur le cycle de vie des pages :
#region Web Form Designer a généré le code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN : cet appel est requis par le concepteur ASP.NET Web Forms.
//
InitializeComponent();
base.OnInit(e);
}
/// <résumé>
/// Designer prend en charge les méthodes requises - n'utilisez pas l'éditeur de code pour modifier
/// Le contenu de cette méthode.
/// </summary>
privé void InitializeComponent()
{
this.DataGrid1.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
C'est le code pour la page générée à l'aide de VS.Net. Jetons un coup d'œil. Il contient deux méthodes, l'une est OnInit et l'autre est InitializeComponent. Cette dernière est appelée par la première. début de l'initialisation de la page. Dans InitializeComponent, nous voyons la déclaration d'événement du contrôle et la déclaration Load de la page.
Ce qui suit est une description extraite de MSDN et un tableau de séquence des méthodes de cycle de vie des pages et du déclenchement d'événements :
"Chaque fois qu'une page ASP.NET est demandée, le serveur charge une page ASP.NET et décharge la page lorsque la demande est terminée. La page et les contrôles serveur qu'elle contient sont responsables de l'exécution de la requête et du rendu du code HTML au client. Bien que la communication entre le client et le serveur soit apatride et intermittente, elle doit être perçue par le client comme un processus continu.
"Cette illusion de continuité est implémentée par le framework de page ASP.NET, la page et ses contrôles. Après une publication, le comportement du contrôle doit sembler commencer là où s'est terminée la dernière requête Web. Les frameworks peuvent rendre la gestion de l'état d'exécution relativement facile, mais pour obtenir des effets de continuité, les développeurs de contrôles doivent connaître l'ordre d'exécution des contrôles. Les développeurs de contrôles doivent comprendre quelles informations peuvent être utilisées et quelles données peuvent être conservées par le contrôle à chaque étape du cycle de vie du contrôle. état dans lequel un contrôle est rendu. Par exemple, un contrôle ne peut pas appeler son parent tant que l'arborescence des contrôles sur la page n'est pas remplie. " Le tableau suivant fournit un aperçu de haut niveau des étapes du cycle de vie du contrôle. Cliquez dans le tableau. lien."
d'étape | doit effectuer une action | pour remplacer la méthode ou l'événement d'initialisation |
initialiser | les paramètres requis dans le cycle de vie d'une requête Web entrante. Voir Gestion des événements hérités. | L'événement Init (méthode OnInit) |
charge l'état d'affichage. | A la fin de cette phase, la propriété ViewState du contrôle sera automatiquement renseignée. Pour plus de détails, voir l'introduction dans Maintenir l'état dans le contrôle. Un contrôle peut remplacer l'implémentation par défaut de la méthode LoadViewState pour la restaurer à un état personnalisé. | La méthode LoadViewState |
gère les données de publication | , traite les données du formulaire entrant et met à jour les propriétés en conséquence. Voir Gestion des données de publication. Remarque Seuls les contrôles qui gèrent les données de publication participent à cette phase. | La méthode LoadPostData (si IPostBackDataHandler est implémenté) |
charge et | exécute des opérations communes à toutes les requêtes, telles que la configuration d'une requête de base de données. À ce stade, les contrôles serveur de l'arborescence ont été créés et initialisés, l'état a été restauré et les contrôles de formulaire reflètent les données du client. Voir Gestion des événements hérités. | Charger un événement (méthode OnLoad) |
Envoyer des notifications de modification de publication | Déclencher un événement de modification en réponse à un changement d'état entre les publications actuelles et précédentes. Voir Gestion des données de publication. Remarque Seuls les contrôles qui déclenchent des événements de modification de publication participent à cette phase. | La méthode RaisePostDataChangedEvent (si IPostBackDataHandler est implémenté) |
gère les événements de publication. | Elle gère les événements client qui provoquent des publications et déclenche les événements appropriés sur le serveur. Voir Capture des événements de publication. Remarque Seuls les contrôles qui gèrent les événements de publication participent à cette phase. | La méthode RaisePostBackEvent (si IPostBackEventHandler est implémentée) |
- | rendus avant de restituer la sortie. Les modifications apportées à l'état d'un contrôle pendant la phase de pré-rendu peuvent être enregistrées, tandis que les modifications apportées pendant la phase de rendu sont perdues. Voir Gestion des événements hérités. | L'événement PreRender (méthode OnPreRender) |
enregistre l'état | après cette phase, en conservant automatiquement la propriété ViewState du contrôle dans un objet chaîne. Cet objet chaîne est envoyé au client et renvoyé en tant que variable cachée. Pour améliorer l'efficacité, les contrôles peuvent remplacer la méthode SaveViewState pour modifier la propriété ViewState. Voir Maintien de l’état dans les contrôles. | La méthode SaveViewState |
restitue | la sortie présentée au client. Voir Rendu des contrôles serveur ASP.NET. | La méthode Render |
gère | toutes les opérations de nettoyage final avant de détruire le contrôle. Les références à des ressources coûteuses, telles que des liens vers des bases de données, doivent être publiées à ce stade. Consultez les méthodes dans les contrôles serveur ASP.NET. | La méthode Dispose |
décharge | toutes les opérations de nettoyage finales avant de détruire le contrôle. Les auteurs de contrôles effectuent généralement un nettoyage dans Dispose sans gérer cet événement. | Événement UnLoad (méthode On UnLoad) |
A partir de ce tableau, nous pouvons clairement voir les méthodes appelées et le temps de déclenchement d'une Page du chargement au déchargement. Ensuite, nous l'analyserons en profondeur.
Après avoir regardé le tableau ci-dessus, des amis attentifs peuvent demander, puisque OnInit est le début du cycle de vie de la page et que nous avons parlé des contrôles créés dans les sous-classes dans la leçon précédente, nous utilisons ici en fait la méthode InitializeComponent. Champs déclarés dans la classe parent peut déjà être utilisé, cela signifie-t-il que la sous-classe est initialisée avant cela ?
Dans le troisième titre, nous avons mentionné que le ProcessRequest de la classe page est le début du cycle de déclaration de page au sens propre du terme. Cette méthode est appelée par HttpApplication (la méthode appelante est plus compliquée, et j'aurai l'occasion d'écrire un). article séparé pour l'expliquer). WebControls.TemplateControl (c'est la page et le contrôle utilisateur. Une méthode virtuelle "FrameworkInitialize" est définie dans la classe de base), puis cette méthode est d'abord appelée dans le ProcessRequest de la Page. Nous avons trouvé des traces de cette méthode dans le code source ASPX. généré par le générateur. Tous les contrôles sont dans Il est initialisé dans cette méthode, et l'arborescence de contrôle de la page est générée à ce moment.
La chose suivante est simple, analysons progressivement chaque élément du cycle de vie de la page :
1. Initialisation
L'initialisation correspond à l'événement Init et à la méthode OnInit de la Page.
Si vous souhaitez réécrire, MSDN recommande de surcharger la méthode OnInti au lieu d'ajouter un proxy pour l'événement Init. Il existe une différence entre les deux. Le premier peut contrôler l'ordre dans lequel la méthode OnInit de la classe parent est appelée, tandis que le premier peut contrôler l'ordre dans lequel la méthode OnInit de la classe parent est appelée. ce dernier ne peut être utilisé que dans la classe parent. Exécuté après OnInit (en fait appelé dans OnInit).
2. Chargement de l'état d'affichage
Il s'agit d'une méthode plus importante. Nous savons que chaque requête est en fait traitée par une instance de classe de page différente. Afin de garantir l'état entre deux requêtes, ASP.Net utilise ViewState.
La méthode LoadViewState obtient le dernier état de ViewState et utilise la récursivité pour parcourir l'intégralité de l'arborescence en fonction de la structure de l'arborescence de contrôle sur la page afin de restaurer l'état correspondant à chaque contrôle.
3. Traitement des données de publication
Cette méthode permet de vérifier si l'état des données de contrôle renvoyées par le client a changé. Prototype de la méthode :
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
postDataKey est le mot-clé qui identifie le contrôle (c'est-à-dire que la clé dans postCollection est une collection contenant des données de publication). le retour Si les données envoyées ont changé, si c'est le cas, il renvoie un True, "LoadPostData renvoie true si l'état du contrôle change en raison de la publication ; sinon, il renvoie false. Le framework de page suit tous les contrôles qui renvoient true et appelle RaisePostDataChangedEvent sur ces contrôles . "(Extrait de MSDN)
Cette méthode est définie dans System.Web.WebControls.Control et est également la méthode que tous les contrôles personnalisés qui doivent gérer les événements doivent gérer. Pour la page dont nous discutons aujourd'hui, vous pouvez la laisser. seul.
4. Loading
correspond à l'événement Load et à la méthode OnLoad. Je pense que la plupart des amis connaissent cet événement. La méthode Page_Load dans la page générée par VS.Net est la méthode pour répondre à l'événement Load. l'événement sera déclenché, la méthode Page_Load sera également exécutée. Je pense que c'est aussi la première étape pour que la plupart des gens comprennent ASP.Net.
La méthode Page_Load répond à l'événement Load, qui est défini dans la classe System.Web.WebControl.Control (cette classe est l'ancêtre de Page et de tous les contrôles serveur) et est déclenchée dans la méthode OnLoad.
De nombreuses personnes ont peut-être rencontré une telle chose. Ils ont écrit une classe PageBase, puis ont vérifié les informations utilisateur dans Page_Load. Il s'est avéré que peu importe si la vérification a réussi ou non, la page Page_Load de la sous-classe sera toujours exécutée en premier. cette fois, certaines informations peuvent être laissées. Pour des raisons de sécurité, l'utilisateur peut exécuter la méthode Page_Load dans la sous-classe sans être authentifié.
La raison de ce problème est très simple, car la méthode Page_Load est ajoutée à l'événement Load dans OnInit, et la méthode OnInit de la sous-classe ajoute d'abord l'événement Load puis appelle base.OnInit, ce qui provoque l'ajout de la sous-classe Page_Load en premier. , puis exécuté en premier.
Il est également très simple de résoudre ce problème. Il existe deux méthodes :
1) Surcharger la méthode OnLoad dans PageBase, puis authentifier l'utilisateur dans OnLoad, puis appeler base.OnLoad, car l'événement Load est déclenché dans OnLoad, nous pouvons donc assurez-vous d'authentifier l'utilisateur avant de déclencher l'événement Load.
2) Appelez d'abord base.OnInit dans la méthode OnInit de la sous-classe pour vous assurer que la classe parent exécute Page_Load en premier.
5. Envoyer une notification de modification de publication.
Cette méthode correspond au traitement des données de publication à l'étape 3. Si les données de publication sont traitées. , True est renvoyé. Le framework de page appellera cette méthode pour déclencher des événements de modification de données, donc l'événement de modification de données de publication du contrôle personnalisé doit être déclenché dans cette méthode.
De même, cette méthode n'est pas très utile pour Page. Bien entendu, vous pouvez également définir des événements de modification de données sur la base de Page.
6. Gérer les événements de publication
Cette méthode est celle où la plupart des événements de contrôle du serveur sont déclenchés. Lorsque la requête contient des informations sur les déclencheurs d'événements de contrôle (les événements des contrôles du serveur sont un autre sujet, j'écrirai un autre article pour en discuter dans un avenir proche), le contrôle de page. La méthode RaisePostBackEvent du contrôle correspondant sera appelée pour déclencher l'événement côté serveur.
Voici une autre question courante :
les internautes demandent souvent pourquoi les données soumises n'ont pas changé après la modification.
Dans la plupart des cas, ils ne comprennent pas le processus de déclenchement des événements du serveur. Nous pouvons voir que l'événement du serveur est déclenché après le chargement de la page. , c'est-à-dire que la page exécutera d'abord Page_Load, puis exécutera l'événement de clic du bouton (voici le bouton à titre d'exemple). De nombreux amis liront les données dans Page_Load, puis traiteront les modifications dans l'événement de bouton. Il y a un problème avec cela, Page_Load est toujours exécuté avant l'événement du bouton, ce qui signifie qu'avant que les données n'aient le temps de changer, le code de liaison de données dans Page_Load est exécuté en premier et les données d'origine sont affectées au contrôle, puis lorsque le L'événement du bouton est exécuté, ce qui est réellement obtenu, ce sont les données originales, donc la mise à jour n'aura bien sûr aucun effet.
Il est également très simple de modifier ce problème. Une approche plus raisonnable consiste à écrire le code de liaison de données dans une méthode, supposons qu'il s'agisse de BindData :
private void BindData().
{
// Lier les données
}
Puis modifiez PageLoad :
private void Page_Load (object sender,EventArgs e)
{
si(!IsPostBack)
{
BindData(); //Lier les données lors du premier accès à la page}
}
Enfin dans l'événement bouton :
private Button1_Click( object sender,EventArgs e )
{
//Mettre à jour dataBindData();//Relier les données
}
7.
Le traitement de la demande finale de pré-rendu sera converti en une réponse renvoyée au serveur. L'étape de pré-rendu consiste à effectuer les changements d'état effectués avant le rendu final, car avant de rendre un contrôle, il faut. générer du HTML en fonction de ses propriétés, comme l'attribut Style, qui est l'exemple le plus typique. Avant le pré-rendu, nous pouvons modifier le style d'un contrôle. Lorsque le pré-rendu est effectué, nous pouvons enregistrer le style et afficher le HTML. informations de style comme étape de rendu.
8. Enregistrez l'état.Cette
étape concerne l'état de chargement.Nous avons mentionné à plusieurs reprises que différentes instances sont traitées entre les requêtes, nous devons donc enregistrer l'état de cette page et contrôler cette étape. .
9. À
ce stade, le traitement des requêtes de la page est pratiquement terminé. Dans la méthode Render, l'arborescence de contrôle de la page entière sera récurée, la méthode Render sera appelée en séquence et le code HTML correspondant sera écrit. dans le flux de réponse final.
10. Disposal
est en fait la méthode Dispose. À ce stade, les ressources occupées, telles que les connexions à la base de données, seront libérées.
11.
À la fin du déchargement, la page exécutera la méthode OnUnLoad pour déclencher l'événement UnLoad, qui gère le traitement final avant la destruction de l'objet de la page. En fait, ASP.Net fournit cet événement uniquement pour des considérations de conception. des ressources est complétée dans la méthode Dispose. Cette méthode est donc devenue inutile.
Nous avons brièvement présenté le cycle de vie de la page et donné une explication moins approfondie du traitement des événements côté serveur. Aujourd'hui, je souhaite principalement que tout le monde comprenne le cycle d'exécution de la page. J'écrirai davantage sur les événements et leur durée de vie. des contrôles de serveur dans le futur article à discuter.
Ces contenus sont quelques-unes de mes expériences de recherche de pages lorsque j'apprenais ASP.Net. Les détails spécifiques ne sont pas discutés en détail. Veuillez vous référer à MSDN pour plus d'informations, mais j'ai cité quelques erreurs courantes commises par les débutants. , j'espère que cela pourra inspirer tout le monde.