1. Базовое введение в серверные сценарии.
Сначала давайте рассмотрим основные методы выполнения страниц веб-сервера:
1. Клиент отправляет запрос на сервер, введя адрес в адресной строке браузера.
2. После того, как сервер получает запрос, он отправляет его на соответствующую серверную страницу (то есть скрипт). Скрипт генерирует ответ от клиента и отправляет его обратно клиенту.
3. Браузер клиента получает ответ от сервера, анализирует его. Html и представляет пользователю графическую веб-страницу. Для
взаимодействия между сервером и клиентом обычно используются следующие основные методы:
1. Форма: это наиболее важный метод, используемый для получения пользовательского ввода. При отправке формы данные отправляются на сервер для обработки.
2. QueryString: при добавлении параметров после URL-адреса параметры передаются на сервер.
3. Файлы cookie: это
.специальный метод, обычно используемый для подтверждения личности пользователя
. 2. ASP.Net Введение
Традиционные серверные языки сценариев, такие как ASP, JSP и т. д., пишут серверные сценарии практически одинаковым образом. Все они встраивают интерпретируемый или скомпилированный и выполняемый код. в Html, а серверная платформа выполняет эти коды для генерации Html-страниц. Жизненный цикл сервлета на самом деле очень прост, то есть весь код выполняется от начала до конца. Конечно, сервлет написан на языке Html. Java может писать более сложный код, но со структурной точки зрения он ничем не отличается от JSP.
Появление ASP.Net сломало эту традицию; ASP.Net приняла технологию CodeBehind и элементы управления на стороне сервера, добавила концепцию событий на стороне сервера, изменила модель написания языка сценариев и стала ближе к программированию в Windows, упростив веб-программирование. интуитивно понятен, но мы должны понимать, что ASP.Net сам по себе не меняет базовую модель веб-программирования, он просто инкапсулирует некоторые детали и предоставляет некоторые простые в использовании функции, в определенной степени упрощающие написание и поддержку кода; экстента, усложняющего способ выполнения на стороне сервера. Это основная тема, которую мы собираемся обсудить сегодня: жизненный цикл веб-страницы ASP.Net.
3. Режим обработки запросов ASP.Net
Мы говорим, что веб-страница ASP.Net не выходит из режима веб-программирования, поэтому она по-прежнему работает в режиме запрос->получение запроса->обработка запроса->отправка ответа. Каждое взаимодействие. с клиентом вызовет новый запрос, поэтому жизненный цикл веб-страницы основан на одном запросе.
Когда IIS получает запрос от клиента, он передает его процессу aspnet_wp для обработки. Этот процесс проверит, существует ли запрошенный домен приложения, если он не существует, он создаст его, а затем создаст среду выполнения Http (). HttpRuntime) для обработки запросов, эта среда выполнения «предоставляет набор служб времени выполнения ASP.NET для текущего приложения» (из MSDN).
Когда HttpRuntime обрабатывает запросы, он поддерживает ряд экземпляров приложения, то есть экземпляров глобального класса приложения (global.asax). Эти экземпляры будут храниться в пуле приложений, когда запросов нет (на самом деле пул приложений поддерживается). другим классом, HttpRuntime — это просто простой вызов). Каждый раз, когда получен запрос, HttpRuntime получает свободный экземпляр для обработки запроса. Этот экземпляр не будет обрабатывать другие запросы до завершения обработки. вернитесь в пул: «Экземпляр используется для обработки нескольких запросов в течение своего существования, но он может обрабатывать только один запрос за раз». (Извлечено из MSDN).
Когда экземпляр приложения обрабатывает запрос, он создает экземпляр класс страницы запроса и выполнить его метод ProcessRequest для обработки запроса. Этот метод является началом жизненного цикла веб-страницы.
4. Страница Aspx и CodeBehind
Прежде чем углубиться в жизненный цикл страницы, давайте сначала обсудим некоторые взаимоотношения между Aspx и CodeBehind.
<%@ Page Language="c#" Codebehind="WebForm.aspx.cs" Inherits="MyNamespace.WebForm" %>
Я считаю, что друзья, которые использовали технологию CodeBehind, должны быть хорошо знакомы с этим предложением в верхней части ASPX. Проанализируйте его один за другим:
Page Language="c#" Само собой разумеется,
Codebehind="WebForm.aspx.cs" Это предложение указывает на связанный файл кода.
Inherits="MyNamespace.WebForm" Это предложение очень важно. Оно представляет имя класса. унаследован страницей, которая является классом в файле кода CodeBehind. Этот класс должен быть производным от System.Web.WebControls.Page.
Из вышеизложенного мы можем понять, что на самом деле класс в CodeBehind является основой страницы. (ASPX). На этом этапе некоторые друзья могут спросить. При написании ASPX вы встраиваете код или серверные элементы управления в Html точно в соответствии с методом ASP. Разве вы не видите тень так называемых «классов». ?
Эта проблема на самом деле несложная. Друзья, использующие программирование ASP.Net, могут перейти на системный диск: WINDOWSMicrosoft.NETFramework<номер версии>Temporary ASP.NET Files и поместить его ниже Все временные файлы ASP. Приложения .Net, существующие на этом компьютере. Имя подкаталога — это имя приложения, а затем идет вниз на два уровня (чтобы обеспечить уникальность, ASP.Net автоматически создает два уровня подкаталогов, а имя подкаталога — это имя). случайный), и тогда мы обнаружим, что существует множество библиотек ссылок, похожих на: «yfy1gjhc.dll», «xeunj5u3.dll» и такие источники, как файлы «komee-bp.0.cs» и «9falckav.0.cs». Фактически, это результат динамической компиляции ASPX с помощью ASP.Net. Когда мы открываем эти исходные файлы, мы можем найти:
public class WebForm_aspx: MyNamespace.WebForm, System.Web.SessionState.IRequiresSessionState.
Это подтверждает наше предыдущее утверждение. , ASPX Это подкласс класса привязки кода. Его имя представляет собой имя файла ASPX плюс суффикс «_aspx». Изучая эти коды, мы можем обнаружить, что фактически все серверные элементы управления, определенные в aspx, генерируются в этих кодах. затем, когда эти коды генерируются динамически, код, изначально встроенный в ASPX, записывается в соответствующем месте.
При первом посещении страницы среда выполнения HTTP будет использовать генератор кода для анализа файла ASPX, генерации исходного кода и его компиляции. Затем последующие посещения будут напрямую вызывать скомпилированную dll. Вот почему ASPX. Причина доступа. очень медленно.
Разъяснив эту проблему, давайте посмотрим на другую проблему. Когда мы используем привязку кода, перетаскиваем элемент управления на страницу дизайна, а затем переключаемся в представление кода, вы можете использовать элемент управления непосредственно в Page_Load. Поскольку элемент управления создается в подклассе, почему его можно использовать в родительском классе? А как насчет прямого использования?
Фактически, мы можем обнаружить, что всякий раз, когда мы используем VS.Net для перетаскивания элемента управления на страницу, в файл привязки кода всегда добавляется оператор, подобный этому:
protected
System.Web.WebControls.Button Button1;
поле «Объявите его как защищенное», а имя соответствует идентификатору элемента управления в ASPX. Если вы внимательно об этом подумаете, эта проблема будет решена. Ранее мы упоминали, что исходный код ASPX динамически генерируется и компилируется генератором. Генератор генерирует код для динамического создания каждого серверного элемента управления. При создании он проверяет, объявил ли родительский класс этот элемент управления. он добавит код, подобный следующему:
this.DataGrid1 = __ctrl;
Эта переменная __ctrl генерирует элемент управления. На данный момент она присваивает ссылку на элемент управления соответствующей переменной в родительском классе, поэтому в. Объявление родительского класса должно быть защищено (на самом деле оно также может быть общедоступным), поскольку необходимо гарантировать, что подклассы смогут его вызывать.
Затем, когда выполняется Page_Load, поскольку объявлению родительского класса было присвоено значение в коде инициализации в подклассе, мы можем использовать это поле для доступа к соответствующему элементу управления. Зная это, мы не будем фиксировать привязку кода, используя элемент управления. в конструкторе в указанном файле вызывает ошибку исключения нулевой ссылки. Поскольку конструктор выполняется первым, инициализация подкласса еще не началась, поэтому поля в родительском классе имеют нулевые значения. Что касается подкласса, мы обсудим это позже. когда класс инициализируется.
5. Жизненный цикл страницы.
Теперь вернемся к содержанию, упомянутому в третьем заголовке, мы говорили об экземпляре HttpApplication, получающем запрос и создающем экземпляр класса страницы. Фактически, этот экземпляр является экземпляром динамически скомпилированного класса ASPX. Из предыдущего заголовка мы узнали, что ASPX на самом деле является подклассом класса привязки кода, поэтому он наследует все защищенные методы.
Теперь давайте посмотрим на код класса CodeBehind, автоматически сгенерированный VS.Net, чтобы начать обсуждение жизненного цикла страницы:
#region Web Form Designer сгенерировал код,
переопределил protected void OnInit(EventArgs e)
{
//
// CODEGEN: этот вызов необходим разработчику веб-форм ASP.NET.
//
ИнициализироватьКомпонент();
base.OnInit(е);
}
/// <сводка>
/// Конструктор поддерживает необходимые методы — не используйте редактор кода для изменения
/// Содержимое этого метода.
/// </summary>
частный void InitializeComponent()
{
this.DataGrid1.ItemDataBound += новый System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound);
this.Load += новый System.EventHandler(this.Page_Load);
}
#endregion
Это код страницы, созданный с помощью VS.Net. В нем есть два метода: один — OnInit, а другой — InitializeComponent. Фактически, это первый. начало инициализации страницы. В InitializeComponent мы видим объявление события элемента управления и объявление загрузки страницы.
Ниже приводится описание, взятое из MSDN, а также таблица последовательности методов жизненного цикла страницы и запуска событий:
«Каждый раз, когда запрашивается страница ASP.NET, сервер загружает страницу ASP.NET и выгружает страницу после завершения запроса. Страница и серверные элементы управления, которые она содержит, отвечают за выполнение запроса и рендеринг HTML клиенту. Хотя связь между клиентом и сервером не имеет состояния и прерывиста, она должна восприниматься клиентом как непрерывный процесс.
«Эта иллюзия непрерывности реализуется структурой страницы ASP.NET, страницей и ее элементами управления. После обратной передачи поведение элемента управления должно начинаться с того места, где закончился последний веб-запрос. Платформы могут сделать управление состоянием выполнения относительно Это легко, но для достижения эффекта непрерывности разработчики средств управления должны знать порядок выполнения средств управления. Разработчикам средств управления необходимо понимать, какая информация может использоваться и какие данные могут сохраняться элементом управления на каждом этапе жизненного цикла средства управления. состояние, в котором отображается элемент управления. Например, элемент управления не может вызвать свой родительский элемент до тех пор, пока дерево элементов управления на странице не будет заполнено». В следующей таблице представлен общий обзор этапов жизненного цикла элемента управления. Щелкните таблицу. связь."
этапом | необходимо выполнить действие | для переопределения метода или события |
инициализации | параметров, необходимых в течение жизненного цикла входящего веб-запроса. См. Обработка унаследованных событий. | Событие Init (метод OnInit) |
загружает состояние представления. | В конце этого этапа свойство ViewState элемента управления будет автоматически заполнено. Подробные сведения см. в разделе «Поддержание состояния в элементе управления». Элемент управления может переопределить реализацию метода LoadViewState по умолчанию, чтобы восстановить его в пользовательское состояние. | Метод LoadViewState |
обрабатывает данные обратной передачи | , обрабатывает входящие данные формы и соответствующим образом обновляет свойства. См. Обработка данных обратной передачи. Примечание. В этом этапе участвуют только элементы управления, обрабатывающие данные обратной передачи. | Метод LoadPostData (если реализован IPostBackDataHandler) |
загружает и | выполняет операции, общие для всех запросов, например настройку запроса к базе данных. На этом этапе серверные элементы управления в дереве созданы и инициализированы, состояние восстановлено, а элементы управления формы отражают данные клиента. См. Обработка унаследованных событий. | Событие загрузки (метод OnLoad). |
Отправка уведомлений об изменениях обратной передачи. | Вызывает событие изменения в ответ на изменение состояния между текущей и предыдущей обратной передачей. См. Обработка данных обратной передачи. Примечание. В этом этапе участвуют только элементы управления, которые вызывают события изменения обратной передачи. | Метод RaisePostDataChangedEvent (если реализован IPostBackDataHandler) |
обрабатывает события обратной передачи. | Он обрабатывает события клиента, вызывающие обратную передачу, и вызывает соответствующие события на сервере. См. Захват событий обратной передачи. Примечание. В этом этапе участвуют только элементы управления, которые обрабатывают события обратной передачи. | Метод RaisePostBackEvent (если реализован IPostBackEventHandler) |
выполняет предварительную | обработку любых обновлений перед отрисовкой вывода. Изменения состояния элемента управления на этапе предварительной отрисовки можно сохранить, тогда как изменения, внесенные на этапе отрисовки, теряются. См. Обработка унаследованных событий. | Событие PreRender (метод OnPreRender) |
сохраняет состояние | после этого этапа, автоматически сохраняя свойство ViewState элемента управления в строковом объекте. Этот строковый объект отправляется клиенту и обратно как скрытая переменная. Чтобы повысить эффективность, элементы управления могут переопределить метод SaveViewState, чтобы изменить свойство ViewState. См. раздел «Поддержание состояния в элементах управления». | Метод SaveViewState |
визуализирует | выходные данные, представленные клиенту. См. Отображение серверных элементов управления ASP.NET. | Метод Render |
обрабатывает | все операции окончательной очистки перед уничтожением элемента управления. На этом этапе необходимо опубликовать ссылки на дорогостоящие ресурсы, например ссылки на базы данных. См. методы в серверных элементах управления ASP.NET. | Метод Dispose |
выгружает | все операции окончательной очистки перед уничтожением элемента управления. Авторы элементов управления обычно выполняют очистку в Dispose, не обрабатывая это событие. | Событие UnLoad (при методе UnLoad). |
Из этой таблицы мы можем ясно видеть вызываемые методы и время срабатывания страницы от загрузки до выгрузки. Далее мы подробно проанализируем ее.
Посмотрев приведенную выше таблицу, внимательные друзья могут спросить, поскольку OnInit — это начало жизненного цикла страницы, а об элементах управления, создаваемых в подклассах, мы говорили в предыдущей лекции, то здесь мы фактически используем метод InitializeComponent Fields, объявленный в родительском классе. уже может быть использован, значит ли это, что подкласс инициализируется до этого?
В третьем заголовке мы упомянули, что ProcessRequest класса страницы — это начало цикла объявления страницы в истинном смысле. Этот метод вызывается HttpApplication (вызывающий метод более сложный, и у меня будет возможность написать его). объяснение этому в отдельной статье). Страница. Обработка запроса начинается с этого метода. Декомпилируя библиотеку классов .Net для просмотра исходного кода, мы нашли базовый класс System.Web.WebControls.Page: System.Web. WebControls.TemplateControl (это страница и пользовательский элемент управления. Виртуальный метод «FrameworkInitialize» определен в базовом классе), а затем этот метод сначала вызывается в ProcessRequest страницы. Мы обнаружили следы этого метода в исходном коде ASPX. генерируется генератором. Все элементы управления находятся в режиме. В этом методе инициализируется, и в это время генерируется дерево элементов управления страницы.
Дальше все просто, давайте постепенно разберем каждый элемент жизненного цикла страницы:
1. Инициализация
Инициализация соответствует событию Init и методу OnInit Страницы.
Если вы хотите переписать, MSDN рекомендует перегрузить метод OnInti вместо добавления прокси-сервера для события Init. Между ними есть разница. Первый может контролировать порядок вызова метода OnInit родительского класса. последний может использоваться только в родительском классе. Выполняется после OnInit (фактически вызывается в OnInit).
2. Загрузка состояния представления
. Это более важный метод. Мы знаем, что каждый запрос фактически обрабатывается отдельным экземпляром класса страницы. Чтобы гарантировать состояние между двумя запросами, ASP.Net использует ViewState.
Метод LoadViewState получает последнее состояние из ViewState и использует рекурсию для обхода всего дерева в соответствии со структурой дерева элементов управления на странице, чтобы восстановить соответствующее состояние для каждого элемента управления.
3. Обработка данных обратной передачи.
Этот метод используется для проверки того, изменился ли статус управляющих данных, отправленных клиентом обратно. Прототип метода:
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
postDataKey — это ключевое слово, идентифицирующее элемент управления (то есть ключ в postCollection). postCollection — это коллекция, содержащая данные обратной передачи, а затем проверить. возврат. Изменились ли отправленные данные; если да, он возвращает True. «LoadPostData возвращает true, если состояние элемента управления изменяется из-за обратной передачи; в противном случае он возвращает false. Платформа страниц отслеживает все элементы управления, которые возвращают true, и вызывает RaisePostDataChangedEvent для этих элементов управления. . "(Извлечено из MSDN)
Этот метод определен в System.Web.WebControls.Control, а также является методом, который должны обрабатывать все пользовательские элементы управления, которым необходимо обрабатывать события. Для страницы, которую мы обсуждаем сегодня, вы можете оставить его. один.
4. Загрузка
соответствует событию Load и методу OnLoad. Я думаю, что большинству друзей знакомо это событие. Метод Page_Load на странице, созданной VS.Net, — это метод ответа на событие Load. событие будет запущено, также будет выполнен метод Page_Load. Я считаю, что это также первый шаг для большинства людей к пониманию ASP.Net.
Метод Page_Load реагирует на событие Load, которое определено в классе System.Web.WebControl.Control (этот класс является предком Page и всех серверных элементов управления) и запускается в методе OnLoad.
Многие люди, возможно, сталкивались с такой вещью. Они написали класс PageBase, а затем проверили информацию о пользователе в Page_Load. Оказалось, что независимо от того, прошла проверка или нет, сначала всегда будет выполняться Page_Load страницы подкласса. на этот раз некоторая информация может остаться. В качестве угрозы безопасности пользователь может выполнить метод Page_Load в подклассе без прохождения аутентификации.
Причина этой проблемы очень проста, поскольку метод Page_Load добавляется к событию Load в OnInit, а метод OnInit подкласса сначала добавляет событие Load, а затем вызывает base.OnInit, что вызывает подкласс. Сначала добавляется Page_Load. , затем выполняется первым.
Решить эту проблему тоже очень просто. Есть два метода:
1) Перегрузить метод OnLoad в PageBase, затем аутентифицировать пользователя в OnLoad, а затем вызвать base.OnLoad, потому что событие Load запускается в OnLoad, поэтому мы можем это сделать. убедитесь, что аутентифицировали пользователя перед запуском события Load.
2) Сначала вызовите base.OnInit в методе OnInit подкласса, чтобы убедиться, что родительский класс первым выполняет Page_Load.
5. Отправьте уведомление об изменении обратной передачи.
Этот метод соответствует обработке данных обратной передачи на шаге 3. Если данные обратной передачи обрабатываются. , возвращается True. Платформа страницы вызовет этот метод для запуска событий изменения данных, поэтому событие изменения данных обратной передачи пользовательского элемента управления должно быть инициировано в этом методе.
Аналогично, этот метод не очень полезен для Page. Конечно, вы также можете определять события изменения данных на основе Page. Это, конечно, тоже возможно.
6. Обработка событий обратной передачи
. Этот метод вызывает большинство событий управления сервером, когда запрос содержит информацию о триггерах событий управления (события элементов управления сервером — это другая тема, я напишу еще одну статью для обсуждения в ближайшем будущем), управление страницей. Будет вызван метод RaisePostBackEvent соответствующего элемента управления, чтобы вызвать событие на стороне сервера.
Возникает еще один распространенный вопрос:
пользователи сети часто спрашивают, почему отправленные данные не изменились после изменения.
В большинстве случаев они не понимают процесс запуска событий сервера. Мы видим, что событие сервера запускается после загрузки страницы. То есть страница сначала выполнит Page_Load, а затем выполнит событие нажатия кнопки (вот пример кнопки). Многие друзья связывают данные в Page_Load, а затем обрабатывают изменения в событии кнопки. с этим проблема, Page_Load всегда выполняется перед событием кнопки, а это означает, что прежде чем данные успеют измениться, сначала выполняется код привязки данных в Page_Load, а исходные данные назначаются элементу управления, а затем, когда Событие кнопки выполняется. На самом деле получаются исходные данные, поэтому обновление, конечно, не будет иметь никакого эффекта.
Изменить эту проблему также очень просто. Более разумный подход — записать код привязки данных в метод, предположим, что это BindData:
Private void BindData().
{
//Привязываем данные
}
Затем измените PageLoad:
Private void Page_Load(отправитель объекта,EventArgs e)
{
если(!Испостбак)
{
BindData(); //Привязываем данные при первом доступе к странице}
}
Наконец, в событии кнопки:
частный Button1_Click(отправитель объекта,EventArgs e)
{
//Обновить данныеBindData();//Перепривязать данные
}
7.
Обработка финального запроса на предварительный рендеринг будет преобразована в ответ, отправленный обратно на сервер. Этап пререндеринга заключается в выполнении изменений состояния, сделанных перед окончательным рендерингом, поскольку перед рендерингом элемента управления мы должны выполнить. генерировать Html на основе его свойств, таких как атрибут Style, который является наиболее типичным примером. Перед предварительной отрисовкой мы можем изменить стиль элемента управления. При выполнении предварительной отрисовки мы можем сохранить стиль и отобразить Html. информация о стиле на этапе рендеринга.
8. Сохранение состояния.
Этот этап предназначен для состояния загрузки. Мы много раз упоминали, что между запросами обрабатываются разные экземпляры, поэтому нам необходимо сохранить состояние этой страницы и управлять этим этапом. .
9. На
этом этапе обработка запроса страницы практически подошла к концу. В методе Render будет рекурсировано дерево управления всей страницей, будет последовательно вызываться метод Render и писаться соответствующий Html-код. в окончательный поток ответов.
10. Disposal
— это фактически метод Dispose. На этом этапе будут освобождены занятые ресурсы, такие как подключения к базе данных.
11.
В конце выгрузки страница выполнит метод OnUnLoad, чтобы вызвать событие UnLoad, которое выполняет окончательную обработку перед уничтожением объекта страницы. Фактически, ASP.Net предоставляет это событие только из соображений проектирования. Обычно при выпуске. ресурсов завершается в методе Dispose, поэтому этот метод стал бесполезным.
Мы кратко представили жизненный цикл страницы и дали менее подробное объяснение обработки событий на стороне сервера. Сегодня я главным образом хочу, чтобы все поняли цикл выполнения страницы. Я напишу еще немного о событиях и времени жизни. управления сервером в будущей статье для обсуждения.
Это содержимое представляет собой часть моего опыта исследования страниц, когда я изучал ASP.Net. Конкретные детали не обсуждаются подробно. Пожалуйста, обратитесь к MSDN для получения дополнительной информации, но я привел некоторые распространенные ошибки и ошибки, допущенные новичками. , Я надеюсь, что это вдохновит каждого.