Файл global.asax
66ASP.NET --- Основы ASP.NET --- Файл global.asax
Файл global.asax позволяет записывать обработчики событий, реагирующие на глобальные события. Пользователи не могут запрашивать файл global.asax напрямую. Файл global.asax выполняет свой код автоматически в ответ на некоторые события приложения.
Код в файле global.asax пишется точно так же, как и для веб-формы. Отличие заключается в том, что файл global.asax не содержит дескрипторов HTML или ASP.NET. Вместо этого он содержит методы со специфическими предопределенными именами.
<%@ Application Language="C#" %>
<script runat="server">
protected void Application_OnEndRequest()
{
Response.Write("<hr />Эта страница была загружена " + DateTime.Now.ToString());
}
</script>
Хотя в показанном коде это не отражено, в каждом файле global.asax определены методы для единственного класса — класса приложения. Класс приложения унаследован от HttpApplication, что позволяет работать в коде со всеми его общедоступными и защищенными членами. В этом примере используется объект Response, который является встроенным свойством класса HttpApplication, точно так же, как и встроенным свойством класса Page.
В предыдущем примере метод Application_OnEndRequest() выводит в нижней части страницы колонтитул с датой и временем ее создания. Поскольку обработчик событий реагирует на событие HttpApplication.EndRequest, метод Application_OnEndRequest() будет выполняться при каждом запросе страницы, сразу же после завершения выполнения всего имеющегося в ней кода обработки событий.
Как и в случае веб-форм, содержимое файла global.asax также можно разнести в два файла: один — с объявлением, а второй — непосредственно с кодом. Однако поскольку поверхности проектирования для файлов global.asax не предусмотрено, в этом нет никакой необходимости, поэтому в Visual Studio и не предлагается опция для создания файла global.asax с классом отделенного кода.
В случае создания веб-приложения как веб-проекта Visual Studio будет применять подход с отделенным кодом и создавать два файла: global.asax (который будет практически пустым) и связанный с ним global.asax.cs (который содержит класс приложения со всеми обработчиками событий). Конечный результат будет точно таким же.
Файл global.asax является необязательным, но каждому веб-приложению разрешено иметь не более одного файла global.asax, который должен находиться в корневом каталоге приложения, а не в каком-то из его подкаталогов. Чтобы добавить файл global.asax в проект, выберите в меню Website (Веб-сайт) (или в меню Project (Проект), если используется модель веб-проекта) пункт Add New Item (Добавить новый элемент) и укажите шаблон Global Application Class (Глобальный класс приложения). (Если в проекте уже присутствует файл global.asax, этот шаблон отображаться не будет.)
При добавлении файла global.asax Visual Studio включает в него пустые обработчики для большинства наиболее распространенных событий приложений, поэтому разработчику остается только поместить свой код в нужные методы.
Стоит отметить, что обработчики событий приложения в файле global.asax присоединяются не так, как обработчики событий обычных элементов управления. Чаще всего для присоединения обработчика событий приложения используется распознаваемое имя метода. Например, если создан защищенный метод по имени Application_OnEndRequest(), то ASP.NET будет автоматически вызывать его при возникновении события HttpApplication.EndRequest. В действительности все зависит от соглашения. Разработчик вполне может решить присоединить обработчик событий к событию HttpApplication.EndRequest, а не предоставлять метод Application_OnEndRequest().
При первой загрузке домена приложения ASP.NET создает пул объектов приложения и использует его для обслуживания каждого запроса. Размер этого пула может варьироваться в зависимости от системы и количества доступных потоков, но обычно включает от 1 до 100 экземпляров. Каждому запросу предоставляется эксклюзивный доступ к одному из этих объектов приложения, а когда обработка запроса завершается, объект становится доступным для повторного использования. По мере прохождения приложением различных стадий обработки ASP.NET вызывает соответствующие методы, которые приводят в действие написанный разработчиком код. Конечно, в случае, если имена методов указаны неправильно, ASP.NET не может вызывать их, и тогда написанный разработчиком код просто игнорируется.
События приложения
В файле global.asax могут обрабатываться события двух следующих типов:
события, которые возникают всегда, для каждого запроса. К числу таких событий относятся события, связанные запросом, и события, связанные с ответом;
события, которые возникают только при определенных условиях.
Обязательные события разворачиваются в описанном ниже порядке:
Application_BeginRequest(). Этот метод вызывается в начале каждого запроса.
Application_AuthenticateRequest(). Этот метод вызывается до того, как будет выполнена аутентификация. Это стартовая точка для создания собственной логики аутентификации.
Application_AuthorizeRequest(). После того как пользователь пройдет процедуру аутентификации (будет идентифицирован), потребуется определить права пользователя. Вы можете использовать этот метод для назначения специальных привилегий.
Application_ResolveRequestCache(). Этот метод обычно используется вместе с кэшированием выходных данных. При кэшировании выходных данных повторно используется сгенерированный HTML-код веб-формы, без выполнения какого-то вашего кода. Однако этот обработчик события по-прежнему продолжает работать.
На этом этапе запрос передается соответствующему обработчику. Например, в случае запроса веб-формы на этом этапе выполняется компиляция страницы (если в этом есть необходимость) и создается ее экземпляр.
Application_AcquireRequestState(). Этот метод вызывается непосредственно перед тем, как касающаяся сеанса информация будет извлечена для клиента и использована для заполнения коллекции Session.
Application_PreRequestHandlerExecute(). Этот метод вызывается перед тем, как соответствующий обработчик HTML выполнит запрос.
В этот момент производится обработка запроса соответствующим обработчиком. Например, если это запрос веб-формы, то выполняется код обработки события для страницы, и для страницы генерируется HTML-код.
Application_PostRequestHandlerExecute(). Этот метод вызывается сразу после того, как будет обработан запрос.
Application_ReleaseRequestState(). Этот метод вызывается тогда, когда информация, специфическая для сеанса, сериализируется из коллекции Session, чтобы стать доступной для следующего запроса.
Application_UpdateRequestCache(). Этот метод вызывается перед добавлением информации в кэш выходных данных. Например, если вы включили кэширование выходных данных для веб-страницы, то ASP.NET в этот момент поместит сгенерированный HTML-код страницы в кэш.
ApplicationEndRequest(). Этот метод вызывается в конце запроса перед тем, как объекты будут освобождены и восстановлены. Это подходящая точка для кода очистки.
На рисунке показан процесс обработки одного запроса:
Некоторые события срабатывают не при каждом запросе:
- Application_Start()
Этот метод вызывается, когда впервые запускается приложение и создается домен приложения. В данный обработчик события удобно помещать код инициализации всего приложения. Например, в этот момент можно загрузить и кэшировать данные, которые не будут изменяться в течение времени жизни приложения; к ним можно отнести деревья навигации, статические каталоги товаров и т.п.
- Session_Start()
Этот метод вызывается каждый раз, когда начинается новый сеанс. Он часто применяется для инициализации информации, специфичной для пользователя.
- Application_Error()
Этот метод вызывается всякий раз, когда в приложении возникает необработанное событие.
- Session_End()
Этот метод вызывается всякий раз, когда сеанс пользователя завершается. Сеанс завершается, когда код явно освобождает его или когда истекает срок его действия из-за отсутствия запросов на протяжении указанного периода времени (обычно 20 минут). Как правило, этот метод применяется для очистки любых связанных с сеансом данных. Однако вызывается этот метод только в том случае, если используется внутрипроцессный режим хранения состояния сеансов (режим InProc, а не StateServer или SQLServer).
- Application_End()
Этот метод вызывается сразу после завершения работы приложения. Завершение работы приложения может произойти либо по причине перезапуска IIS, либо вследствие перехода приложения в новый домен приложения в ответ на обновление файлов или параметров настроек повторного использования процесса.
- Application_Disposed()
Этот метод вызывается спустя какое-то время после завершения работы приложения, когда сборщик мусора .NET готов к восстановлению занимаемой приложением памяти. В этот момент уже поздно выполнять критическую очистку, хотя можно в последний раз узнать, были ли освобождены критические ресурсы.
События приложений обычно используются для выполнения инициализации приложения, очистки, регистрации использования, профилирования и поиска и устранения неисправностей. Однако не следует думать, что приложению обязательно нужны глобальные события приложения. Многие приложения ASP.NET вообще не используют файл global.asax.
Файл global.asax не является единственным местом, где можно реагировать на глобальные события веб-приложений. Можно также создать специальные модули, принимающие участие в обработке веб-запросов.
Демонстрация событий приложения
В следующем веб-приложении используется файл global.asax, который реагирует на событие HttpApplication.Error. Он перехватывает ошибку и отображает некоторую информацию в предопределенном формате:
<%@ Application Language="C#" %>
<script runat="server">
void Application_Error(object sender, EventArgs e)
{
Response.Write("<b>Возникла ошибка: </b><hr/>");
Response.Write(Server.GetLastError().Message.ToString() + "<hr/>" + Server.GetLastError().ToString());
Server.ClearError();
}
</script>
Чтобы протестировать этот обработчик событий приложения, понадобится создать еще одну веб-страницу, вызывающую ошибку. Ниже показан пример, который генерирует ошибку при попытке выполнить во время загрузки страницы операцию деления на ноль:
protected void Page_Load(object sender, EventArgs e)
{
int j = 8;
int k = 0;
int i = j / k;
}
Запросив эту страницу, вы увидите следующий результат:
Обычно вы не будете использовать метод ApplicationError(), поскольку он не обладает достаточной гибкостью для работы с различными типами ошибок (если только не предусмотреть большой объем условного кода). Конфигурировать страницы специальных ошибок можно с использованием IIS. Однако метод ApplicationError() может оказаться чрезвычайно полезным, если вы захотите зарегистрировать ошибку, чтобы исследовать ее в будущем или даже отправить администратору системы электронное письмо с уведомлением о ней. В действительности, во многих случаях вам понадобятся именно эти технологии, поскольку объект Response не будет доступен. Двумя такими примерами являются методы Application_Start() и Application_End().