Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
protected void btnAddToVS_Click(object sender, EventArgs е) {
ViewState["CustomViewStateItem"] = "Пользовательские данные";
lblVSValue.Text = (string)ViewState["CustomViewStateItem"];
}
Тип System.Web.UI.StateBag может работать с любым типом, производным от System.Object. Поэтому, чтобы получить доступ к значению данного ключа, вам нужно явно преобразовать его в правильный тип данных (в данном случае это тип System.String). При этом следует учесть, что размещаемое в поле __VIEWSTATE значение не может быть абсолютно любым объектом. Единственными действительными типами в данном случае являются строки, цельте числа, булевы значения, типы ArrayList, и Hashtable, а также массивы этих типов.
Но если страницы *.aspx могут вставлять пользовательские фрагменты информации в строку __VIEWSTATE, было бы неплохо выяснить, как это сделать. Как правило, пользовательские данные состояния представлений используются для установки настроек пользователя. Например, вы можете создать элемент данных представления, указывающий то, каким пользователь желает видеть GridView (например, с точки зрения порядка сортировки). Но данные состояния представлений не очень хорошо подходят для "развёрнутых" пользовательских данных, таких как объекты в корзине покупателя, помещенные в кэш типы DataSet или какие-то другие специальные типы. Когда требуется запомнить сложную информацию, лучше работать с сеансовыми данными. Но перед тем как перейти к соответствующему разделу нашего обсуждения, мы должны выяснить роль файла Global.asax.
Исходный код. Файлы примера ViewStateApp размещены в подкаталоге, соответствующем главе 24.
Несколько слов о данных состояния элементов
В ASP.NET 2.0 предлагается поддержка состояний элементов управления, а не только состояния представлений. Эта технология оказывается очень удобной при работе с созданными вами Web-элементами управления ASP.NET, которые должны сохранять свои данные между последовательными циклами запросов. Для этого, конечно, можно использовать и свойство ViewState, но если учет состояния представлений будет отключен на уровне страницы, пользовательский элемент управления работать не будет. Именно по этой причине Web-элементы управления теперь поддерживают свойства ControlState.
Состояния элементов управления используются аналогично состояниям представлений, но учет состояния элементов управления не отключается при отключении учета состояния представлений на уровне страницы. Как уже говорилось, эта возможность оказывается наиболее полезной для разработчиков пользовательских Web-элементов управления (обсуждение данной темы в нашей книге не предполагается). За подробностями обратитесь к документации .NET Framework 2.0 SDK.
Роль файла Global.asax
К этому моменту у вас может сложиться впечатление, что приложение ASP.NET представляет собой простой набор файлов *.аsрх и соответствующих Web-элементов управления. И хотя вы можете построить Web-приложение с помощью простого связывания нескольких Web-страниц, вам, скорее всего, хотелось бы иметь возможность взаимодействия с Web-приложением, как с чем-то цельным. Для этого в Web-приложение ASP.NET можно включить необязательный файл Global.asax, выбрав WebSite→Add New Item из меню (рис. 24.2).
Рис. 24.2. Добавление файла Global.asax
В некотором смысле файл Global.asax в ASP.NET аналогичен традиционному файлу *.exe, поскольку представляет поведение Web-узла в среде выполнения. После добавления файла Global.asax в Web-проект вы обнаружите, что этот файл на самом деле представляет собой блок ‹script›, содержащий набор обработчиков событий.
‹%@ Application Language="C#" %›
‹script runat="server"›
void Application_Start(Object sender, EventArgs e) {
// Код, выполняемый при запуске приложения.
}
void Application_End(Object sender, EventArgs e) {
// Код, выполняемый при завершении приложения.
}
void Applicatioт_Error(Object sender, EventArgs e) {
// Код, выполняемый при появлении необработанной ошибки.
}
void Session_Start(Object sender, EventArgs e) {
// Код, выполняемый при открытии нового сеанса.
}
void Session_End(Object sender, EventArgs e) {
// Код, выполняемый при завершении сеанса.
}
‹/script›
Однако первое впечатление может оказаться обманчивым. В среде выполнении программный код этого блока ‹script› преобразуется в тип класса, получающийся из System.Web.HttpApplication. Если вы имеете опыт работы с ASP.NET 1.х, то вы, наверное, вспомните, что там файл с внешним кодом поддержки для Global.asax буквально определял класс, получающийся из HttpApplication.
Как уже было сказано, члены, определённые в Global.asax, содержатся в обработчиках событий, позволяющих взаимодействовать с событиями на уровне приложения (а также сеанса). Описания этих членов предлагаются в табл. 24.1.
Таблица 24.1. Обработчики событий Global.asax
Обработчик события Описание Аррlication_Start() Вызывается только при запуске Web-приложения, поэтому генерируется только один раз за все время выполнения Web-приложения. Является идеальным местом для определения данных уровня приложения, доступных в любой точке Web-приложения Application_End() Вызывается при завершении работы приложения, например, вследствие превышения времени ожидания для последнего пользователя или при завершении работы приложения вручную с помощью IIS Session_Start() Вызывается при регистрации нового пользователя в приложении. Здесь можно установить параметры, связанные с конкретным пользователем Session_End() Вызывается при завершении сеанса пользователя (обычно в результате превышения установленного времени ожидания) Application_Error() Глобальный обработчик ошибок, который вызывается тогда, когда Web-приложение генерирует необработанное исключениеПоследний глобальный шанс для обработки исключений
Позвольте указать на роль обработчика событий Application_Error(). Напомним, что страница может использовать обработчик события Error для обработки любого исключения, сгенерированного в контексте страницы и оставшегося без обработки. Обработчик Application_Error() оказывается последним пунктом возможной обработки исключений, которые не были обработаны на уровне страницы. Как и в случае события Error на уровне страницы, вы можете получить доступ к конкретному объекту System.Exception, используя наследуемое свойство Server.
void Application_Error(Object sender, EventArgs e) {
Exception ex = Server.GetLastError();
Response.Write(ex.Message);
Server.ClearError();
}
Обработчик Application Error() является "последним шансом" обработки события для вашего Web-приложения, где вы, вместо предъявления сообщения об ошибке пользователю, можете записать соответствующую информацию в журнал регистрации событий Web-сервера, например:
‹%@ Import Namespace = "System.Diagnostics"%›
…
void Application_Error(Object sender, EventArgs e) {
// Запись последнего события в журнал событий.
Exception ex = Server.GetLastError();
EventLog ev = new EventLog("Application");
ev.WriteEntry(ex.Message, EventLogEntryType.Error);
Server.ClearError();
Response.Write("Это приложение "зависло". Извините!");
}
Базовый класс HttpApplication
Как уже говорилось, сценарий Global.asax динамически преобразуется в класс, который получается из базового класса System.Web.HttpApplication и обеспечивает те же функциональные возможности, что и тип System.Web.UI.Page. Описания соответствующих членов предлагаются в табл. 24.2.
Таблица 24.2. Ключевые члены типа System.Web.HttpApplication
Свойство Описание Application Позволяет взаимодействовать с переменными уровня приложения, используя доступный тип HttpApplicationState Request Позволяет взаимодействовать с входящим HTTP-запросом (с помощью HttpRequest) Response Позволяет взаимодействовать с HTTP-ответом (с помощью HttpResponse) Server Получает внутренний объект сервера для текущего запроса (с помощью HttpServerUtilitу) Session Позволяет взаимодействовать с переменными уровня сеанса, используя доступный тип HttpSessionStateРазличия между приложением и сеансом